Использование Netwire для создания списков значений

Я думаю, что я принципиально не понимаю, как атаковать этот тип проблемы с Netwire:

У меня есть следующий тест-кейс:

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

Куски, которые мне не хватает:

  • Как запретить после значения в начале конвейера, но затем, если это значение будет разделено, а результаты получены позже, не запрещать, пока все эти результаты не будут использованы.
  • Как должна выглядеть функция основного цикла
  • Если я должен использовать "один раз"

Вот код, который у меня есть:

import Control.Wire

main :: IO ()
main = recur mainWire

recur :: Wire () IO () () -> IO ()
recur a = do
  (e,w) <- stepWire a 0 ()
  case e of Left  () -> return ()
            Right () -> recur w

mainWire :: Wire () IO () ()
mainWire = pure "asdf\nqwer\nzxcv"
       >>> once
       >>> arr lines
       >>> fifo
       >>> arr print
       >>> perform

Это выводит следующее:

"asdf"

и затем выходит. Если я удалю once, затем программа работает как положено, многократно выводя полный список строк навсегда.

Я хотел бы следующий вывод:

"asdf"
"qwer"
"zxcv"

Я уверен, что мне здесь не хватает интуиции о том, как правильно подойти к этому классу проблем с Netwire.

1 ответ

Решение

Примечание. Это для более старой версии netwire (раньше события работали так, как они работают сейчас), поэтому для корректной работы с текущей версией необходим некоторый перевод кода.


Если я вас правильно понял, вам нужен провод, который производит строки строки, а затем запрещает, когда с этим покончено? Сложно сказать.

once как следует из названия, производит ровно один раз, а затем тормозит навсегда. Опять же, немного неясно, что делают ваши провода (потому что вы не сказали нам), но это не то, что вы обычно кладете в свой "основной" провод (до сих пор я когда-либо использовал только once с andThen).

Если это правильно, я бы, вероятно, сделал что-то вроде:

produceLines s = produceLines' $ lines s where
  produceLines' [] = inhibit mempty
  produceLines' (l:ls) = pure s . once --> produceLines' ls

(Вы могли бы написать это как фолд или что-то вроде того, я просто подумал, что это немного яснее).

--> хорош для andThen если ты не знал По сути, это разбивает переданную строку на строки и превращает их в провод, который производит первую строку один раз, а затем ведет себя как аналогичный провод, за исключением того, что первый элемент удален. Это блокирует неопределенно, как только все значения были произведены.

Это то, что вы хотели?

Обновить

Я вижу, что вы пытались сделать сейчас.

Провод, который вы пытались написать, можно сделать как

perform . arr print . fifo . ((arr lines . pure "asdf\nqwer\nzxcv" . once) --> pure [])

Часть в скобках производят ["adf","nqwer","nzxc"] на одно мгновение, а затем производит [] навсегда. fifo берет значения из предыдущего проводника, добавляя результат из предыдущего проводника в каждом случае (из-за этого мы должны продолжать производить []). Остальное, как вы знаете (я использую функциональную нотацию, а не стрелку, потому что я предпочитаю, но это не должно быть проблемой для вас).

Другие вопросы по тегам