Запуск потребителя внутри трубы

Мне нужно составить потребитель и трубу так, чтобы выход потребителя питал вход трубы.

Я думаю, это можно решить с помощью комбинатора, подобного этому:

Consumer i m r -> (r -> Producer o m r') -> Pipe i o m r'

или это:

Consumer i m i' -> Pipe i' o m r -> Pipe i o m r

или подъемная функция, подобная следующей:

Consumer i m r -> Pipe i o m r

или вот так:

Consumer i m o -> Pipe i o m r

Я пытался сделать consumer >~ pipe безуспешно. Итак, как подойти к этому?


person Nikita Volkov    schedule 14.07.2014    source источник
comment
Вы предполагаете, что потребитель будет запускаться несколько раз?   -  person danidiaz    schedule 14.07.2014
comment
Нет, я не собираюсь этого делать.   -  person Nikita Volkov    schedule 14.07.2014


Ответы (2)


Что-то похожее на вашу подпись Consumer i m o -> Pipe i o m r можно сделать так:

{-# LANGUAGE RankNTypes #-}
import Pipes

foo :: Monad m => Consumer' i m o -> Pipe i o m ()
foo consumer = consumer >>= yield

Я использовал синоним полиморфного типа Consumer', который, поскольку он на самом деле не закрыт «ниже по течению», может использоваться как Pipe, который на самом деле никогда не yields. Чтобы заставить его возвращать значение потребителя, мы просто используем монадическую привязку.

Что касается вашей подписи Consumer i m r -> Pipe i o m r, это просто идентификатор, использующий синоним полиморфного типа:

iden :: Monad m => Consumer' i m r -> Pipe i o m r
iden consumer = consumer
person danidiaz    schedule 14.07.2014

Для вашей подписи первого типа, если ваши Consumer и Producer используют синонимы полиморфного типа Consumer' и Producer', то вам нужен комбинатор (>>=):

(>>=) :: Pipe i o m r -> (r -> Pipe i o m r') -> Pipe i o m r'

Consumer' i m r будет проверять тип как Pipe i o m r. Точно так же Producer' o m r' будет проверять тип как Pipe i o m r'.

person Gabriel Gonzalez    schedule 14.07.2014