为什么在使用sinkVector和runConduit时会得到非矢量类型?

时间:2019-01-24 20:26:08

标签: haskell conduit

我有一个具有此类型签名的管道:

processFileName :: (MonadResource m, MonadThrow m, PrimMonad m) =>
  ConduitT FilePath (MapRow Text) m ()

以下使用它的管道构造函数进行类型检查:

readFnameData2 ::MonadResource m => ConduitT (MapRow Text) FilePath m ()
  -> ConduitT (MapRow Text) Void m (Vector (MapRow Text))
readFnameData2 files = files
    .| processFileName
    .| sinkVector

但是,当我尝试修改它以在Vector单子中实际返回IO时,我得到了意外的结果:

readFnameData ::MonadResource m => ConduitT (MapRow Text) FilePath m () -> IO (Vector (MapRow Text))
readFnameData files = do
  fNameRows <- files
   .| processFileName
   .| sinkVector
  fNameRows & runConduit

产生错误:

    * Couldn't match type `Map Text Text' with `Vector (MapRow Text)'
      Expected type: IO (Vector (MapRow Text))
        Actual type: IO (MapRow Text)
    * In a stmt of a 'do' block: fNameRows & runConduit
      In the expression:
        do fNameRows <- files .| processFileName .| sinkVector
           fNameRows & runConduit
      In an equation for `readFnameData':
          readFnameData files
            = do fNameRows <- files .| processFileName .| sinkVector
                 fNameRows & runConduit
   |
70 |       fNameRows & runConduit
   |       ^^^^^^^^^^^^^^^^^^^^^^

我觉得我这里必定缺少一些基本知识,但不确定要看什么才能揭开谜底。

更新:要在下面详细说明我的第一条评论,我们可以看到中间的ConduitT错误:

    readFnameData3 ::MonadResource m => ConduitT (MapRow Text) FilePath m ()
      -> IO (Vector (MapRow Text))
    readFnameData3 files = runConduit (readFnameData2 files)

    * Couldn't match type `Map Text Text' with `()'
      Expected type: ConduitT () Void m (Vector (MapRow Text))
        Actual type: ConduitT (MapRow Text) Void m (Vector (MapRow Text))
    * In the first argument of `runConduit', namely
        `(readFnameData2 files)'
      In the expression: runConduit (readFnameData2 files)
      In an equation for `readFnameData3':
          readFnameData3 files = runConduit (readFnameData2 files)
   |
67 |     readFnameData3 files = runConduit (readFnameData2 files)      
   |                                        ^^^^^^^^^^^^^^^^^^^^

这显示ConduitT的第一个字段的类型不匹配。不确定sinkVector为什么不为此返回单元类型,因为所有runConduit*似乎都在该位置具有单位,并且由于它是一个接收器,它不能接受其他有意义的输入,因此我想这应该是()-尽管不确定为什么Void并不是更好的选择。

1 个答案:

答案 0 :(得分:0)

我可以将中间函数更正为

readFnameData2 ::MonadResource m => ConduitT () FilePath m ()
  -> ConduitT () Void m (Vector (MapRow Text))
readFnameData2 files = files
    .| processFileName
    .| sinkVector

readFnameData3 ::MonadResource m => ConduitT () FilePath m ()
  -> m (Vector (MapRow Text))
readFnameData3 files = runConduit (readFnameData2 files)

这里的问题是files应该具有单位输入类型,可以作为源!

readFnameData ::MonadResource m => ConduitT () FilePath m () -> m (Vector (MapRow Text))
readFnameData files = runConduit $ files .| processFileName .| sinkVector