【问题标题】:Why is there an unexpected "expected type" of () in this conduit composition (fusion)?为什么在这个管道组合(融合)中有一个意想不到的“预期类型”的()?
【发布时间】:2019-09-26 00:11:43
【问题描述】:

我将以下导管组件融合在一起:

awaitVals () :: ConduitT (Element mono) (Element mono) m ()
intermTmp :: forall o. (Element mono -> Bool) -> ConduitT (Element mono) o m ([Element mono])

融合发生如下:awaitVals () .| intermTmp curPred

根据熔断函数(.|),我觉得这里的类型应该没问题。保险丝是:

(.|) :: Monad m
     => ConduitT a b m ()
     -> ConduitT b c m r
     -> ConduitT a c m r

这是整个函数定义:

takeWhileGrouped :: forall m mono. (Monad m, MonoFoldable mono) =>
  ([Element mono -> Bool])
  -> ConduitT (Element mono) [Element mono] m ()
takeWhileGrouped preds = go preds
  where
    go (curPred:nextPreds) = yieldM (goIter curPred) >> go nextPreds
    go [] = yield []
    intermTmp :: forall o. (Element mono -> Bool) -> ConduitT (Element mono) o m ([Element mono])
    intermTmp curPred = CC.takeWhile curPred .| sinkList
    goIter :: (Element mono -> Bool) -> m ([Element mono])
    goIter curPred =
      (awaitVals () :: ConduitT (Element mono) (Element mono) m ())
        .| (intermTmp curPred) & runConduit

awaitVals :: forall a m. Monad m => () -> ConduitT a a m ()
awaitVals _ = do
  nextValMay <- await
  case nextValMay of
    Just val -> do
      yield val
      awaitVals ()
    Nothing -> pure ()

这是错误:

    • Couldn't match type ‘Element mono’ with ‘()’
      Expected type: ConduitM () () m ()
        Actual type: ConduitT (Element mono) (Element mono) m ()
    • In the first argument of ‘(.|)’, namely
        ‘(awaitVals () :: ConduitT (Element mono) (Element mono) m ())’
      In the first argument of ‘(&)’, namely
        ‘(awaitVals () :: ConduitT (Element mono) (Element mono) m ())
           .| (intermTmp curPred)’
      In the expression:
        (awaitVals () :: ConduitT (Element mono) (Element mono) m ())
          .| (intermTmp curPred)
          & runConduit
    • Relevant bindings include
        curPred :: Element mono -> Bool
          (bound at src/FDS/Data/Conduits.hs:151:12)
        goIter :: (Element mono -> Bool) -> m [Element mono]
          (bound at src/FDS/Data/Conduits.hs:151:5)
        intermTmp :: forall o.
                     (Element mono -> Bool)
                     -> ConduitT (Element mono) o m [Element mono]
          (bound at src/FDS/Data/Conduits.hs:149:5)
        preds :: [Element mono -> Bool]
          (bound at src/FDS/Data/Conduits.hs:144:18)
        takeWhileGrouped :: [Element mono -> Bool]
                            -> ConduitT (Element mono) [Element mono] m ()
          (bound at src/FDS/Data/Conduits.hs:144:1)
    |
151 |     goIter curPred = (awaitVals () :: ConduitT (Element mono) (Element mono) m ()) .| (intermTmp curPred) & runConduit
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我不明白为什么预期的类型与实际的类型不一致。 这是一个更一般的问题,我还没有完全解决,但它确实有一个接近尾声的工作解决方案(但它不使用保险丝在最外层组成导管):How to implement a takeWhile-like function using Conduit combinators? 应该是睡了一个合理的时间再看这个吧,但是我很好奇这个……

【问题讨论】:

  • 我刚刚注意到消息中有一个ConduitM,但显然type ConduitM = ConduitT,所以这不是问题。
  • 我开始意识到这个问题与runConduit(及其所有变体)有关,在输入位置期望(),并且相关地,我没有“来源”可以包含单位当前写入的输入位置....嗯

标签: haskell conduit


【解决方案1】:

原因是runConduit 要求() 在它所传递的管道组件的输入类型中。但这显然不是我们这里所拥有的:我们需要一个来源,而在这种情况下我们只是没有一个。那么我们需要在不使用runConduit的情况下实现该功能,所以我们不能再构造中介管道。请参阅 How to implement a takeWhile-like function using Conduit combinators? 了解可行的实现。

注意:我在使用了以下管道后得出了这个结论,这些管道可以更容易地了解类型和组成变化的情况。注释掉的示例无法编译。

testCondComposedSink :: forall i o m. Monad m => ConduitT i o m [i]
testCondComposedSink = awaitVals () .| sinkList

testCondComposedTakeW :: forall i m. Monad m => ConduitT i i m ()
testCondComposedTakeW = awaitVals () .| CC.takeWhile (\_ -> True)

testCondComposedAll :: forall i o m. Monad m => ConduitT i o m [i]
testCondComposedAll = awaitVals () .| CC.takeWhile (\_ -> True) .| sinkList

takeWhileSinkList :: forall i o m. Monad m => (i -> Bool) -> ConduitT i o m [i]
takeWhileSinkList predicate = CC.takeWhile predicate .| sinkList

testCondComposedAll2 :: forall i o m. Monad m => ConduitT i o m [i]
testCondComposedAll2 = awaitVals () .| takeWhileSinkList (\_ -> True)

-- testCondComposedAll2Run ::  forall i m. Monad m => m [i]
-- testCondComposedAll2Run = testCondComposedAll2 & runConduit

-- takeWhileSinkList2 :: forall i m. Monad m => (i -> Bool) -> ConduitT () Void m [i]
-- takeWhileSinkList2 predicate = CC.takeWhile predicate .| sinkList

-- testCondComposedAll3 :: forall i o m. Monad m => ConduitT () o m [i]
-- testCondComposedAll3 = awaitVals () .| takeWhileSinkList2 (\_ -> True)

-- testCondComposedAll3Run ::  forall i m. Monad m => m [i]
-- testCondComposedAll3Run = testCondComposedAll3 & runConduit

-- testCondDownsteram :: forall i o r m. Monad m => () -> ConduitT i o m r
-- testCondDownsteram = undefined

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-16
    • 2022-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    相关资源
    最近更新 更多