Почему в этом составе канала (слияние) есть неожиданный «ожидаемый тип» ()? - PullRequest
1 голос
/ 26 сентября 2019

У меня есть следующие компоненты трубопровода, которые сливаются вместе:

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
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Я не понимаю, почему ожидаемыйТип не согласуется с фактическим типом.Вот более общий вопрос, который я не полностью завершил, но у него есть рабочее решение ближе к концу (но он не использует плавкий предохранитель для создания каналов на самом внешнем уровне): Как реализовать takeWhile-как функция с использованием комбинаторов Conduit? Вероятно, мне стоит подождать, чтобы посмотреть на это после того, как я поспал достаточно, но мне было очень любопытно по этому поводу ...

1 Ответ

0 голосов
/ 26 сентября 2019

Причина в том, что runConduit требует, чтобы () был указан в качестве типа ввода компонента канала, через который он передается.Но это явно не то, что мы имеем здесь: нам нужен источник для этого, и у нас просто нет его в этом контексте.Затем нам нужно реализовать функцию без использования runConduit, чтобы мы больше не могли строить промежуточные каналы.См. Как реализовать функцию, подобную takeWhile, используя комбинаторы Conduit? для реализации, которая работает.

Примечание : я пришел к такому выводу, поиграв со следующимканалы, которые сделали немного легче увидеть, что происходит с типами и вариациями в составе.Закомментированные примеры имеют проблемы с компиляцией.

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
...