Getting confused with MonadBaseControl errors while learning Conduits in Haskell

138 views Asked by At

I'm trying go learn about Conduits in Haskell. It sounds interesting, but the types are quickly getting extremely confusing.

I've got the following file written so far: https://gist.github.com/anonymous/7991727

Presumably, what it would do is that, given a series of ticker symbols, it would go to Yahoo Finance and download the associated data file. Sounds simple enough.

getLink and extractLink works great. No problems there.

downloadContent is giving me all sorts of compile problems. This source code:

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

The exact error I'm getting is this:

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.

What is the insight here that will let me accomplish the intent of the code?

1

There are 1 answers

1
John Wiegley On

You will have to lift your actions to the underlying monad of your conduit:

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