Таким образом, я выполняю некоторое начальное упражнение главы Реального мира Haskell, и я хотел знать, существует ли опция в GHCi, чтобы заставить его показать функциональную оценку с параметрами на каждом рекурсивном вызове. Так, например, я записал простую версию 'карты', и когда я применяю ее, я хотел бы, чтобы GHCi отобразил каждый рекурсивный вызов с действительными аргументами (и надо надеяться результаты выражения). Что-то, что позволяет мне следовать за тем, что продолжается негласно.
P.S., Поскольку я пишу это, у меня есть чувство, что это может быть ограничено ленью модели выполнения haskell, исправить меня, если я неправ.
Я бы порекомендовал посмотреть на вопрос Как мне получить стек вызовов в Haskell? и Ответ Дона Стюарта со связанными руководствами по использованию ghci для отладки
Вы можете использовать hood для этого:
import Debug.Hood.Observe
map2 f [] = []
map2 f (x:xs) = f x : (observe "map2" $ map2) f xs
main = runO $ print $ map2 (+1) ([1..10] :: [Int])
Когда вы запустите его, он выведет каждый вызов map2 с соответствующими аргументами и результат, который был возвращен. Вы увидите что-то вроде:
.
.
.
-- map2
{ \ { \ 10 -> 11
, \ 9 -> 10
} (9 : 10 : [])
-> 10 : 11 : []
}
-- map2
{ \ { \ 10 -> 11
} (10 : [])
-> 11 : []
}
-- map2
{ \ _ [] -> []
}
Для получения дополнительной информации проверьте примеры.
Я обычно использую Debug.Trace :
import Debug.Trace
buggy acc xs | traceShow (acc,xs) False = undefined
buggy acc [] = acc
buggy acc (x:xs) = buggy (acc + x) xs
main = print $ buggy 0 [1..10]
Это позволяет мне увидеть, как работает функция с ошибками:
(0,[1,2,3,4,5,6,7,8,9,10])
(1,[2,3,4,5,6,7,8,9,10])
(3,[3,4,5,6,7,8,9,10])
(6,[4,5,6,7,8,9,10])
(10,[5,6,7,8,9,10])
(15,[6,7,8,9,10])
(21,[7,8,9,10])
(28,[8,9,10])
(36,[9,10])
(45,[10])
(55,[])
55
key имеет шаблон, который никогда не совпадает, но что-то печатает, хотя он не совпадает. Таким образом, он всегда оценивается (и, следовательно, распечатывает отладочную информацию), и его легко привязать к любой функции. Но вы также можете сделать его совпадающим, если хотите увидеть только определенные случаи, например:
buggy acc [] = acc
buggy acc (x:xs) | traceShow (acc, x, xs) True = buggy (acc + x) xs
Тогда вы получите отладочную информацию только для не-базового случая:
(0,1,[2,3,4,5,6,7,8,9,10])
(1,2,[3,4,5,6,7,8,9,10])
(3,3,[4,5,6,7,8,9,10])
(6,4,[5,6,7,8,9,10])
(10,5,[6,7,8,9,10])
(15,6,[7,8,9,10])
(21,7,[8,9,10])
(28,8,[9,10])
(36,9,[10])
(45,10,[])
55
YMMV.