问题
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