Почему я получаю не векторный тип при использовании sinkVector и runConduit? - PullRequest
0 голосов
/ 24 января 2019

У меня есть канал с такой подписью типа:

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 голосов
/ 25 января 2019

Я могу исправить промежуточные функции, чтобы они были

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