How do I use expandable effects and IO?
I'm trying to rewrite the examples from the article to the new version of the extensible-effects package 1.11.0.0, but I get "Failed to output ..." when I try to use the lift for the IO monad :(
ghc 7.10.1
{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, TypeOperators #-}
{-# LANGUAGE DeriveFunctor, DeriveDataTypeable #-}
module Main where
import Data.Typeable
import Control.Eff
import Control.Eff.Lift
data Log v = Log String v deriving (Functor, Typeable)
log' :: Member Log r => String -> Eff r ()
log' txt = send . inj $ Log txt ()
verboseAddition :: Member Log r => Eff r Int
verboseAddition = do
log' "I'm starting with 1..."
x <- return 1
log' "and I'm adding 2..."
y <- return 2
let r = x + y
log' $ "Looks like the result is " ++ show r
return r
runLogger :: Eff (Log :> r) a -> Eff r ([String],a)
runLogger = loop
where
prefixLogWith txt (l,v) = (txt:l, v)
loop = freeMap
(\x -> return ([], x))
(\u -> handleRelay u loop
$ \(Log txt next) -> fmap (prefixLogWith txt) (loop next))
runIOLogger :: SetMember Lift (Lift IO) r => Eff (Log :> r) a -> Eff r a
runIOLogger = loop
where
loop = freeMap
return
(\u -> handleRelay u loop
$ \(Log txt next) ->
lift (putStrLn txt) >> -- Could not deduce ... :(
loop next)
main:: IO ()
main = -- print $ run $ runLogger verboseAddition -- ok
runLift (runIOLogger verboseAddition) >>= print
Could not deduce (extensible-effects-1.11.0.0:Data.OpenUnion.Internal.Base.M emberUImpl
extensible-effects-1.11.0.0:Data.OpenUnion.Internal.Open Union2.OU2
Lift
(Lift IO)
r)
arising from a use of `lift'
from the context (SetMember Lift (Lift IO) r)
bound by the type signature for
runIOLogger :: SetMember Lift (Lift IO) r =>
Eff (Log :> r) a -> Eff r a
at src\Main.hs:37:16-72
In the first argument of `(>>)', namely `lift (putStrLn txt)'
In the expression: lift (putStrLn txt) >> loop next
In the second argument of `($)', namely
`\ (Log txt next) -> lift (putStrLn txt) >> loop next'
+3
source to share
1 answer
It works:
runIOLogger :: SetMember Lift (Lift IO) r => Eff (Log :> r) a -> Eff r a
runIOLogger = freeMap
return
(\u -> handleRelay u runIOLogger $ \(Log txt next) -> do
lift $ putStrLn txt
runIOLogger next)
Besides:
runIOLogger :: SetMember Lift (Lift IO) r => Eff (Log :> r) a -> Eff r a
runIOLogger = loop
where
loop :: SetMember Lift (Lift IO) r => Eff (Log :> r) a -> Eff r a
loop = freeMap
return
(\u -> handleRelay u loop
$ \(Log txt next) ->
lift (putStrLn txt) >> -- Could not deduce ... :(
loop next)
id' a = fst (a, id' (a, a))
But this is fine:
id' :: a -> a
id' a = fst (a, id' (a, a))
I'm pretty sure there is something like this here, but I haven't tried to figure out exactly where the output is going.
+4
source to share