Marek Sapota
Marek Sapota

Reputation: 20591

Manipulating the monad stack

If I have a stack of monads, say IO, State and Error, and a function that only uses IO and Error. How would one go about "removing" the middle State monad from the stack so I can use my function? If the order was IO, Error, State, I could use lift to match the types, but I want to be able to use my function if the monad stack contains IO and Error and possibly other monads in whatever order. For example:

fun :: ErrorT String IO ()
fun = throwError "error"

someCode :: ErrorT String (StateT Int IO) ()
someCode = do
    -- I want to use fun here

Upvotes: 11

Views: 359

Answers (1)

David Miani
David Miani

Reputation: 14668

Just change the type signature of fun to fun :: (MonadError String m, MonadIO m) => m (). It will then be usable for any monad stack that have a String Error, and can perform IO (such as ErrorT String (StateT Int IO)).

Eg:

fun :: (MonadError String m, MonadIO m) => m ()
fun = do
  liftIO $ putStrLn "in fun"
  throwError "error"

someCode :: ErrorT String (StateT Int IO) ()
someCode = do
  fun
  -- whatever you want

Upvotes: 15

Related Questions