Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lift error value to ErrorT monad transformer

I think I'm missing some basic understanding of monad transformers, because I found myself writing this code:

import Control.Monad.Identity
import Control.Monad.Error

liftError :: Either String Int -> ErrorT String Identity Int
liftError x = do case x of
                    Right val -> return val
                    Left err -> throwError err

gateway :: Bool -> ErrorT String Identity Int
gateway = liftError . inner

inner :: Bool -> Either String Int
inner True = return 5
inner False = throwError "test"

While this works, I think that this could be done more elegantly. In particular, I'm looking for a replacement of liftError, which I think I shouldn't have to define for myself.

What would be the most straightforward way to make gateway and inner work together without changing their type?

like image 450
Niklas B. Avatar asked Apr 04 '12 17:04

Niklas B.


1 Answers

If you just change the types a little, you don't have to do any lifting at all.

{-# LANGUAGE FlexibleContexts #-}

gateway :: Bool -> ErrorT String Identity Int
gateway = inner

inner :: MonadError String m => Bool -> m Int
inner True = return 5
inner False = throwError "test"

MonadError has instances for both ErrorT and Either, so this way you can use inner as both.

like image 147
hammar Avatar answered Oct 30 '22 20:10

hammar