{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Data.Model.Util
(
Errors
, toErrors
, noErrors
, errsInContext
, inContext
, errorToConvertResult
, errorsToConvertResult
, convertResultToError
, convertResultToErrors
, convertOrError
, Convertible(..)
, convert
, ConvertResult
, ConvertError(..)
, dotted
) where
import Data.Bifunctor
import Data.Convertible
import Data.Convertible.Tiny()
import Data.Typeable
import Data.List
type Errors = [Error]
type Error = String
toErrors :: Bifunctor p => p a c -> p [a] c
toErrors = first (: [])
noErrors :: Errors -> Bool
noErrors = null
errorToConvertResult
:: (Typeable b, Typeable a, Show a)
=> (a -> Either Error b)
-> a
-> ConvertResult b
errorToConvertResult conv a = either (`convError` a) Right $ conv a
errorsToConvertResult
:: (Typeable b, Typeable t, Show t)
=> (t -> Either Errors b)
-> t
-> ConvertResult b
errorsToConvertResult conv a =
either (\errs -> convError (intercalate ", " errs) a) Right $ conv a
convertOrError :: Convertible a c => a -> Either String c
convertOrError = convertResultToError . safeConvert
convertResultToError :: Bifunctor p => p ConvertError c -> p String c
convertResultToError = first prettyConvertError
convertResultToErrors :: Bifunctor p => p ConvertError c -> p [String] c
convertResultToErrors = toErrors . convertResultToError
errsInContext
:: (Convertible ctx String, Bifunctor p)
=> ctx
-> p [String] c
-> p [String] c
errsInContext ctx = first (inContext ctx)
inContext :: Convertible ctx String => ctx -> [String] -> [String]
inContext ctx = map (\msg -> unwords ["In", convert ctx ++ ":", msg])
dotted :: [String] -> String
dotted [] = ""
dotted [s ] = s
dotted (h:t) = post h ++ dotted t
where
post s | null s = ""
| otherwise = s ++ "."