
Hello Group, Recently I discovered for my self an alternative for monad transformers - extensible effects. http://okmij.org/ftp/Haskell/extensible/ Overall it is really cool and Eff1.hs started working right away, but I noticed a problem with mixing several effects in 1 function. Type checker requires pretty verbose type signature, which looks unreasonable plus the error reported to a beginner developer is not intuitive. So my questions are: - why it happens? - what could I do to get more friendly error message? - is there a workaround enforcing GHC make an extra mile and work without these "extra hints"? - any more maintainable Eff implementations? Here it an example I wish should working. $ stack gchi Eff1.hs *Eff1 > doLift = lift (putStrLn "EFF!") *Eff1 > doWrite = tell "HELLO" *Eff1 > doLiftAndWrite = doLift >> doWrite *Eff1 > runLift (runWriter doLiftAndWrite) <interactive>:82:20: error: * Couldn't match type `Writer [Char]' with `Lift IO' arising from a use of `doLiftAndWrite' * In the first argument of `runWriter', namely `doLiftAndWrite' In the first argument of `runLift', namely `(runWriter doLiftAndWrite)' In the expression: runLift (runWriter doLiftAndWrite) The error message looks unclear, because documentation makes me think that Writer and Lift are members of same Eff monad and they are composable and doLiftAndWrite has been evaluated successfully. And my workaround: *Eff1 > runLift $ do { x :: ((), [String]) <- runWriter doLiftAndWrite; return x; } EFF! ((),["HELLO"]) Plus GHCi swallows a type error: *Eff1 > badCast = do { x :: ((), [Int]) <- runWriter doLiftAndWrite; return x; } *Eff1 > :t badCast badCast :: (MemberU2 Lift (Lift IO) r, OpenUnion52.FindElem (Writer [Char]) r) => Eff r ((), [Int]) Definitely Extensible Effects are more flexible that MTL, but compile type safety looks jeopardized. Type verbosity overhead is kind of acceptable, but having possibility of run-time errors is too big price for flexibility. -- Daneel S. Yaitskov