在Haskell中学习管道时,与MonadBaseControl错误混淆

时间:2013-12-16 18:26:06

标签: http haskell conduit

我正在尝试去了解Haskell中的管道。这听起来很有趣,但这些类型很快变得非常混乱。

到目前为止,我已经写了以下文件:https://gist.github.com/anonymous/7991727

据推测,它会做的是,给定一系列股票代码符号,它将转到Yahoo Finance并下载相关的数据文件。听起来很简单。

getLinkextractLink效果很好。没问题。

downloadContent给了我各种编译问题。这个源代码:

downloadContent manager = do
  mx <- await
  case mx of
    Nothing               -> return ()
    Just (sym, Nothing)   -> return ()
    Just (sym, Just link) -> do
      req <- parseUrl link
      res <- http req manager
      responseBody res $$+- sinkFile sym

我得到的确切错误是:

src/suckyahoo.hs:58:21:
    No instance for (MonadBaseControl
                       IO
                       (ConduitM
                          [Char] ([Char], Maybe String) (ResourceT (ResourceT IO))))
      arising from a use of `getLink'
    Possible fix:
      add an instance declaration for
      (MonadBaseControl
         IO
         (ConduitM
            [Char] ([Char], Maybe String) (ResourceT (ResourceT IO))))
    In the second argument of `($=)', namely `getLink manager'
    In the first argument of `($$)', namely
      `sourceSyms $= getLink manager'
    In a stmt of a 'do' block:
      sourceSyms $= getLink manager $$ downloadContent manager

src/suckyahoo.hs:58:40:
    No instance for (MonadBaseControl
                       IO
                       (ConduitM
                          (FilePath, Maybe String)
                          void-0.6.1:Data.Void.Void
                          (ResourceT (ResourceT IO))))
      arising from a use of `downloadContent'
    Possible fix:
      add an instance declaration for
      (MonadBaseControl
         IO
         (ConduitM
            (FilePath, Maybe String)
            void-0.6.1:Data.Void.Void
            (ResourceT (ResourceT IO))))
    In the second argument of `($$)', namely `downloadContent manager'
    In a stmt of a 'do' block:
      sourceSyms $= getLink manager $$ downloadContent manager
    In the expression:
      do { sourceSyms $= getLink manager $$ downloadContent manager }
Failed, modules loaded: none.

这里有什么洞察力可以让我实现代码的意图?

1 个答案:

答案 0 :(得分:1)

您必须将行动提升到管道的基础单子:

downloadContent manager = do
  mx <- await
  case mx of
    Nothing               -> return ()
    Just (sym, Nothing)   -> return ()
    Just (sym, Just link) -> lift $ do
      req <- parseUrl link
      res <- http req manager
      responseBody res $$+- sinkFile sym