gpt4 book ai didi

haskell - 如何使用可扩展效果和IO?

转载 作者:行者123 更新时间:2023-12-02 13:16:56 25 4
gpt4 key购买 nike

我正在尝试重写 article 中的示例到新版本的包extensible-effects 1.11.0.0,但当我尝试使用 IO monad 的 lift 时,我得到“无法推断...”:(

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'

最佳答案

这有效:

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递归绑定(bind)的多态类型,相反,它首先假设递归绑定(bind)变量是单态的来推断类型,然后概括结果类型。这意味着只有当我们使用递归绑定(bind)的不同实例时,类型推断才会失败。例如,这无法检查:

id' a = fst (a, id' (a, a))

但这很好:

id' :: a -> a
id' a = fst (a, id' (a, a))

我很确定这里存在这样的问题,尽管我还没有努力找出推理到底在哪里停止了。

关于haskell - 如何使用可扩展效果和IO?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31516829/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com