Вы хотите, чтобы
foldAndPropagateConstants [("x", parse "1+2+3"), ("y", parse "5*x + 7"), ("z", parse "x+y-1")]
было эквивалентно
= let s0 = []
r1 = parse' "1+2+3" s0
-- r1 = Leaf (Constant 6)
s1 = [("x",6)]
r2 = parse' "5*x + 7" s1
-- r2 = Leaf (Constant 37)
s2 = [("x",6),("y",37)]
r3 = parse' "x+y-1" s2
-- r3 = Leaf (Constant 42)
s3 = [("x",6),("y",37),("z",42)]
in
[r1,r2,r3]
parse'
похоже на parse
, но оно также может обратиться к хранилищу значений, известных так дальний, который он получает в качестве второго аргумента.
Вышеприведенное легче кодируется функциями, если его реструктурировать как
= let s0 = []
(s1, r1) = parse'' "1+2+3" s0
-- r1 = Leaf (Constant 6)
-- s1 = [("x",6)]
(s2, r2) = parse'' "5*x + 7" s1
-- r2 = Leaf (Constant 37)
-- s2 = [("x",6),("y",37)]
(s3, r3) = parse'' "x+y-1" s2
-- r3 = Leaf (Constant 42)
-- s3 = [("x",6),("y",37),("z",42)]
in
snd (s3, [r1,r2,r3])
Кстати, этот шаблон вычислений с передачей состояний известен как государственная монада, но это вопрос другого дня.
Вышеуказанное соответствует шаблону рекурсия , когда выражается как
foldAndPropagateConstants [("x", parse "1+2+3"), ("y", parse "5*x + 7"), ("z", parse "x+y-1")] =
snd $ foldAndPropagateConstants'
[("x", parse "1+2+3"), ("y", parse "5*x + 7"), ("z", parse "x+y-1")]
[]
foldAndPropagateConstants' [("x", parse "1+2+3"), ("y", parse "5*x + 7"), ("z", parse "x+y-1")] s0 =
let
(s1, r1) = parse'' "1+2+3" s0
(sn, rs) = foldAndPropagateConstants' [("y", parse "5*x + 7"), ("z", parse "x+y-1")] s1
in
(sn, r1 : rs)
-- and
foldAndPropagateConstants' [] s0 = (s0, [])
А теперь, Обобщение! (путем замены значения примера символом c единица).