问题
I have the following conduit components that are being fused together:
awaitVals () :: ConduitT (Element mono) (Element mono) m ()
intermTmp :: forall o. (Element mono -> Bool) -> ConduitT (Element mono) o m ([Element mono])
The fusion occurs like: awaitVals () .| intermTmp curPred
.
According to the fuse function (.|
), I think the types should be OK here. Fuse is:
(.|) :: Monad m
=> ConduitT a b m ()
-> ConduitT b c m r
-> ConduitT a c m r
Here's the entire function definition:
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 ()
And here is the error:
• 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I don't understand why the expected type disagrees with the actual type. Here's a more general question that I haven't totally wrapped up, but it does have a working solution near the end (but it doesn't use fuse to compose conduits at the outermost level): How to implement a takeWhile-like function using Conduit combinators? I should probably wait to look at this after having slept a reasonable amount, but I was very curious about this...
回答1:
The reason is that runConduit
requires ()
to be in the input type of the conduit component it is passed. But that is clearly not what we have here: we need a source for that, and we just don't have one in this context. Then we need to implement the function without using runConduit
, so we can no longer construct intermediary conduits. See How to implement a takeWhile-like function using Conduit combinators? for an implementation that works.
Note: I came to this conclusion after playing out with the following conduits that made it a bit easier to see what was happening with types and variation in composition. The commented out examples have trouble compiling.
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
来源:https://stackoverflow.com/questions/58107971/why-is-there-an-unexpected-expected-type-of-in-this-conduit-composition-fu