[Haskell-cafe] Eff verbose/ambiguous/type safety

Daneel Yaitskov dyaitskov at gmail.com
Mon Apr 13 05:46:53 UTC 2020

Hello Group,

Recently I discovered for my self an alternative for monad
transformers - extensible effects.


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; }

Plus GHCi swallows a type error:
*Eff1 > badCast = do { x :: ((), [Int]) <- runWriter doLiftAndWrite; return x; }
*Eff1 > :t 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

More information about the Haskell-Cafe mailing list