Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中将Writer monad与导管一起使用_Haskell_Monads_Conduit - Fatal编程技术网

在Haskell中将Writer monad与导管一起使用

在Haskell中将Writer monad与导管一起使用,haskell,monads,conduit,Haskell,Monads,Conduit,作为学习Haskell、导管和单子的练习,我想创建一个导管,告诉输入值并传递它 代码非常简单,但我得到的编译错误对我来说仍然很神秘: log = await >>= \case Nothing -> return () Just value -> do tell [value] yield value runWriter $ CL.sourceList ["a", "b"] $= log $$ CL.c

作为学习Haskell、导管和单子的练习,我想创建一个导管,告诉输入值并传递它

代码非常简单,但我得到的编译错误对我来说仍然很神秘:

 log =
    await >>= \case
      Nothing -> return ()
      Just value -> do
        tell [value]
        yield value

 runWriter $ CL.sourceList ["a", "b"] $= log $$ CL.consume
错误是:

 No instance for (MonadWriter [o0] m0) arising from a use of ‘tell’
 The type variables ‘m0’, ‘o0’ are ambiguous
 Relevant bindings include
   value :: o0
     (bound at /home/vagrant/workspace/dup/app/Main.hs:241:10)
   logg :: ConduitM o0 o0 m0 ()
     (bound at /home/vagrant/workspace/dup/app/Main.hs:238:1)
 Note: there are several potential instances:
   instance MonadWriter w m => MonadWriter w (ConduitM i o m)
     -- Defined in ‘conduit-1.2.6.4:Data.Conduit.Internal.Conduit’
   instance MonadWriter w m =>
            MonadWriter
              w (conduit-1.2.6.4:Data.Conduit.Internal.Pipe.Pipe l i o u m)
     -- Defined in ‘conduit-1.2.6.4:Data.Conduit.Internal.Pipe’
   instance [safe] MonadWriter w m =>
                   MonadWriter w  (Control.Monad.Trans.Resource.Internal.ResourceT m)
     -- Defined in ‘Control.Monad.Trans.Resource.Internal’
   ...plus 11 others
 In a stmt of a 'do' block: tell [value]
 In the expression:
  do { tell [value];
       yield value }
 In a case alternative:
    Just value
      -> do { tell [value];
              yield value }

以下是对我有效的方法:

{-# LANGUAGE FlexibleContexts #-}

import Data.Conduit
import Control.Monad.Writer
import qualified Data.Conduit.List as CL

doit :: MonadWriter [i] m => Conduit i m i
doit = do
  x <- await
  case x of
    Nothing -> return ()
    Just v  -> do tell [v]; yield v; doit

foo = runWriter $ CL.sourceList ["a", "b", "c"] =$= doit $$ CL.consume
您将得到两个错误:

No instance for (Monad m0) arising from a use of ‘await’
...

No instance for (MonadWriter [o0] m0) arising from a use of ‘tell’
...
因为
doit
是一个顶级函数,经验会告诉你 也许单态限制在这里起作用。 事实上,在加入:

{-# LANGUAGE NoMonomorphismRestriction #-}
您只会得到一个错误:

Non type-variable argument in the constraint: MonadWriter [o] m
(Use FlexibleContexts to permit this)
...
添加
FlexibleContexts
后,代码将编译

现在您可以查询
doit
的类型:

ghci> :t doit
doit :: MonadWriter [o] m => ConduitM o o m ()

这种类型为我检查是否与导入有关?顺便说一句,您可能希望
log
管道在第一个项目到达后继续运行。因为只有一个项目可以通过。因此,您应该递归地循环,或者使用
waitiveforever
或类似的方法。谢谢@ErikR您的回答。如果您能解释如何从错误消息推断类型签名,我将不胜感激。
ghci> :t doit
doit :: MonadWriter [o] m => ConduitM o o m ()