ghci отображает стек выполнения

Итак, я работаю над некоторыми начальными упражнениями по главе Real World Haskell, и я хотел знать, есть ли в GHCi опция, позволяющая отображать оценку функции с параметрами при каждом рекурсивном вызове. Так, например, я написал простую версию «карты», и когда я ее применяю, я хотел бы, чтобы GHCi отображал каждый рекурсивный вызов с фактическими аргументами (и, надеюсь, результатами выражения). Что-то, что позволяет мне следить за тем, что происходит за кулисами.

P.S. Когда я пишу это, у меня возникает ощущение, что это может быть ограничено ленивостью модели выполнения Haskell, поправьте меня, если я ошибаюсь.


person Archit Baweja    schedule 12.07.2010    source источник
comment
возможный дубликат Как получить стек вызовов в Haskell?   -  person rampion    schedule 12.07.2010
comment
Не совсем дубликат этого.   -  person jrockway    schedule 12.07.2010


Ответы (3)


Я бы рекомендовал рассмотреть вопрос Как мне получить стек вызовов в Haskell? и ответ Дона Стюарта со связанными руководствами как использовать ghci для отладки

person rampion    schedule 12.07.2010

Вы можете использовать капюшон для этого:

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
{ \ _ []  -> []
}

Дополнительные сведения см. в примерах.

person Daniel    schedule 12.07.2010

Обычно я использую Debug .Трассировка:

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

Ключ имеет шаблон, который никогда не совпадает, но печатает что-то, пока он не соответствует. Таким образом, он всегда оценивается (и, следовательно, выводит отладочную информацию), и его легко привязать к любой функции. Но вы также можете сделать так, чтобы оно совпадало, если вы хотите видеть только определенные случаи, например:

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.

person jrockway    schedule 12.07.2010