Мне довольно комфортно с остальными механизмами стрелок, но я не понимаю, как работает цикл.Это кажется мне волшебным, и это плохо для моего понимания.У меня также есть проблемы с пониманием mfix.Когда я смотрю на фрагмент кода, который использует rec
в блоке proc
или do
, я запутываюсь.С помощью обычного монадического кода или кода со стрелкой я могу выполнять вычисления и сохранять оперативную картину того, что происходит в моей голове.Когда я добираюсь до rec
, я не знаю, какую фотографию оставить!Я застреваю и не могу рассуждать о таком коде.
Пример, который я пытаюсь найти, взят из бумаги Росса Патерсона о стрелках , про схемы.
counter :: ArrowCircuit a => a Bool Int
counter = proc reset -> do
rec output <- returnA -< if reset then 0 else next
next <- delay 0 -< output+1
returnA -< output
Я предполагаю, что если я пойму этот пример, то смогу понять цикл в целом, и он станет отличным способом понимания mfix.Они чувствуют, по существу, то же самое для меня, но, возможно, есть тонкость, которую я скучаю?Как бы то ни было, что я действительно ценю, так это оперативное изображение таких фрагментов кода, так что я могу просматривать их в своей голове, как «обычный» код.
Редактировать : Благодаря ответу Pigworker, я начал думать о rec и таких требованиях, которые выполняются.Взяв пример counter
, первая строка блока rec требует значение, называемое output
.Я представляю себе это как создание поля, пометив его output
и попросив блок rec заполнить это поле.Чтобы заполнить это поле, мы вводим значение в returnA, но само это значение требует другого значения, называемого next
.Чтобы использовать это значение, оно должно запрашиваться из другой строки в блоке записи , но не имеет значения, где в блоке записи оно требуется, пока .
Итак, мы переходим к следующей строке и находим поле с надписью next
, и мы требуем, чтобы другие вычисления заполнили его.Теперь это вычисление требует нашего первого окна!Таким образом, мы даем ему поле , но оно не имеет значения внутри него, поэтому, если это вычисление требует содержимого output
, мы попадаем в бесконечный цикл.К счастью, задержка принимает коробку, но создает значение, не заглядывая внутрь коробки.Это заполняет next
, что позволяет нам заполнить output
.Теперь, когда output
заполнен, при обработке следующего входа этой схемы предыдущее поле output
будет иметь свое значение, готовое к требованию для получения следующего next
и, следовательно, следующего output
.
Как это звучит?