我试图将示例从article改写为新版本的程序包extensible-effects 1.11.0.0,但我得到了"无法推断...& #34;当我尝试使用电梯进行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'
答案 0 :(得分:4)
这有效:
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)
以及:
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)
用于递归绑定的GHC can't infer多态类型,相反,它首先推断出一种类型,假设递归约束变量是单态的,然后推广结果类型。这意味着如果我们使用递归绑定的不同实例化,则类型推断仅会失败。例如,这无法检查:
id' a = fst (a, id' (a, a))
但这很好:
id' :: a -> a
id' a = fst (a, id' (a, a))
我很确定这样的问题就是这里的问题,尽管我还没有努力找出确切的停止在哪里。