Я пытаюсь понять один из примеров, представленных на руководство по каналам относительно ListT
:
import Pipes
import qualified Pipes.Prelude as P
input :: Producer String IO ()
input = P.stdinLn >-> P.takeWhile (/= "quit")
name :: ListT IO String
name = do
firstName <- Select input
lastName <- Select input
return (firstName ++ " " ++ lastName)
Если запустить приведенный выше пример, мы получим следующий вывод:
>>> runEffect $ every name >-> P.stdoutLn
Daniel<Enter>
Fischer<Enter>
Daniel Fischer
Wagner<Enter>
Daniel Wagner
quit<Enter>
Donald<Enter>
Stewart<Enter>
Donald Stewart
Duck<Enter>
Donald Duck
quit<Enter>
quit<Enter>
>>>
Кажется, что:
- Когда вы запустите это (на ghci), первое введенное вами имя будет привязано, и изменится только второе. Я ожидаю, что оба производителя (определенные
Select input
) будут по очереди (возможно, недетерминировано) при чтении ввода. - Ввод
quit
один раз позволит повторно связать имя. Опять же, я не понимаю, почемуfirstName
будет привязан к первому значению, введенному пользователем. - Если ввести
quit
два раза подряд, программа завершится. Однако я ожидаю, чтоquit
нужно будет ввести только дважды, чтобы выйти из программы (возможно, чередуя с другим вводом).
Мне не хватает чего-то фундаментального в том, как работает приведенный выше пример, но я не могу понять, что именно.