Фон
Я проходил через John Hughes Программирование со стрелками, и я чувствовал, что у меня все прямо в голове, пока следующее пример использования mapA:
>runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]]
[[0,0,0],[1,2,3],[4,5,6]]
Если runSF извлекает функцию потока из стрелки StreamFunction, определяемую как:
newtype SF a b = SF {runSF :: [a]->[b]}
И задержка определяется как:
delay x = SF (init . (x:))
SF - это экземпляр ArrowChoice (который объявляет mapA) и, таким образом, экземпляр Arrow.
Мое понимание
mapA :: arr a b -> arr [a] [b]
delay :: SF a b
так что delay
просто добавляет второй аргумент своей первой.
Таким образом, mapA (delay 0)
должен вернуть нам стрелку SF, которая принимает [[a]]
и возвращает [[b]]
mapA (delay 0) :: SF [[a]] [[b]]
Я ожидал бы, что "схема", в которой это приведет:
В тех случаях, когда цифры обозначают части процесса:
- Для любого непустого
list x
,listcase
будет выдаватьRight(x, xs)
. Для пустого спискаlistcase
будет выдаватьLeft()
, терминал. - Значения с тегами
Right
будут переданы в нижнюю часть. Значения с тегамиLeft
будут переданы вconst[]
, что существенно остановит итерацию. - При вводе
(x, xs)
,x
будет передан в(delay 0)
, аxs
будет передан обратно наlistcase
. - Результат 3 будет
(z, zs)
, который передается вuncurry (:)
, который присоединяет кортеж к списку.
Вот мое понимание потока, с входом [[1,2,3],[4,5,6],[7,8,9]]
:
-
Первый проход
-
Right ([1,2,3],[[4,5,6],[7,8,9]])
-
([1,2,3], [[4,5,6],[7,8,9]])
передается в нижнюю часть -
(delay 0)
вызывается на[1,2,3]
, что приводит к[0,1,2]
.[[4,5,6],[7,8,9]]
возвращается кlistcase
-
-
Второй проход
-
Right ([4,5,6], [[7,8,9]])
-
([4,5,6], [[7,8,9]])
передается в нижнюю часть -
(delay 0)
вызывается на[4,5,6]
, что приводит к[0,4,5]
.[[7,8,9]]
возвращается кlistcase
-
-
Третий проход
-
Right ([7,8,9], [])
-
([7,8,9], [])
передается в нижнюю часть -
(delay 0)
вызывается на[7,8,9]
, что приводит к[0,7,8]
.[]
возвращается кlistcase
.
-
-
Четвертый проход
-
Left ()
, упал на пол.
-
В этот момент мы переходим к части 4, которая выводит результат 3 и объединяет все это вместе. По существу, мы строим операцию:
[0,1,2] : [[0,4,5] : [[0,7,8] : []]]
Что даст нам [[0,1,2],[0,4,5],[0,7,8]]
.
Мое замешательство
Понятно, что мой поток выше ошибочен.
Как вызов runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]]
приводит к [[0,0,0],[1,2,3],[4,5,6]]
?