А вот, кстати, при проверке лямбда-калькуляторов, написанных студентами, возникла такая задачка.
Пускай мы реализовали на Хаскелле лямбда-термы
data Term =
Var String
| App Term Term
| Lam String Term
проверку их альфа-эквивалентности (можно и точное совпадение, для наших целей не важно):
alphaEq :: Term -> Term -> Bool
и
(
Read more... )
Comments 27
(The comment has been removed)
Reply
reduceToNF показывает все итерации, кроме последней :))
Ведь это имеется в виду, да?
reduceToNF term = unfoldr step (term,True) where
step t,False = Nothing
step t,True = let next = reduce t in
Just(t, not $ t `alphaEq` next)
После чего сразу захотелось плюнуть на unfoldr и сделать то же самое на iterate / takeWhile...
Тем более, что она по смыслу более точно подходит: у нас список итераций.
reduceToNF reduce equal = map fst . takeWhile snd . iterate (step . fst) . (,True)
where
step t =
let n = reduce t in
(t, not $ t `alphaEq` n)
Ибо, один чёрт мы заворачиваем-выворачиваем значения, только вместо Maybe Term здесь (Term,Bool).
Reply
Тут есть другая бяка в схеме, которую, кстати, непонятно каким test suit'ом ловить. Эта схема врёт на одном достаточно просто устроенном терме.
Reply
Я предполагаю, что оно может возникнуть по 4 причинам:
1) баг в alphaEq, который некоторые эквивалентные термы не считает таковыми
2) баг в reduce, приводящий к циклу длиной более 1 либо к "как это будет редукция наоборот"
3) терм, описывающий рекурсивное выражение, который при редукции не сокращается, а раскрывается всё больше и больше
4) подлинно рекурсивный терм, вида let t = App t t in t - для которого синтаксическое дерево анализировать бесполезно, нужна редукция на графе
Reply
Reply
Leave a comment