Excepts (ExceptT-like approach)ΒΆ
Just like ExceptT e m a
wraps Either e a
, we can use a Excepts es m a
newtype to wraps a
VEither es a.
Example:
import Haskus.Utils.Variant.Excepts
import Prelude hiding (head,lookup)
import qualified Prelude
import Text.Read
data ParseError = ParseError deriving Show
parse :: String -> Excepts '[ParseError] IO Integer
parse s = case readMaybe s of
Just i -> pure i
Nothing -> throwE ParseError
data HeadError = ListWasEmpty deriving Show
head :: [a] -> Excepts '[HeadError] IO a
head [] = throwE ListWasEmpty
head (x:_) = pure x
data LookupError k = KeyWasNotPresent k deriving Show
lookup :: Eq k => k -> [(k,v)] -> Excepts '[LookupError k] IO v
lookup k vs = case Prelude.lookup k vs of
Just v -> pure v
Nothing -> throwE (KeyWasNotPresent k)
foo :: String -> Excepts '[ParseError, LookupError Char, HeadError] IO Integer
-- foo :: forall es.
-- ('[HeadError,ParseError,LookupError Char] :<< es
-- ) => String -> Excepts es IO Integer
foo str = do
c <- liftE $ head str
r <- liftE $ lookup c codeMap
liftE $ parse (r ++ tail str)
where
codeMap :: [(Char, String)]
codeMap = [ ('x', "0x")
, ('d', "")
]
Test:
> runE (foo "d10")
VRight 10
> runE (foo "x10")
VRight 16
> runE (foo "u10")
VLeft KeyWasNotPresent 'u'
> runE (foo "")
VLeft ListWasEmpty
> runE (foo "d10X")
VLeft ParseError
> runE (foo "" `catchE` (\ListWasEmpty -> success 42) :: Excepts '[ParseError,LookupError Char] IO Integer)
VRight 42