Этот вопрос, по сути, дублирует Отладка бесконечных циклов в программах Haskell с помощью GHCi . Автор решил это вручную, хотя я хотел бы знать другие решения .
У меня есть код стрелки, который содержит рекурсивный вызов,
testAVFunctor = proc x -> do
y <- errorArrow "good error" -< x
z <- isError -< y
(passError ||| testAVFunctor) -< trace "value of z" z
errorArrow
должен заставить рекурсивный testAVFunctor не выполняться, поскольку это вызовет isError чтобы вернуть Left (AVError "хорошая ошибка" )
, который, в свою очередь, должен выбрать маршрут passError
и обойти рекурсивный вызов.
Очень странно то, что вставка вызовов "трассировки" на популярных сайтах, таких как композиция функций, приводит к тому, что программа генерирует конечный объем вывода, затем замораживание. Не то, что я ожидал бы от задачи бесконечного расширения. (см. правку 1)
Я загрузил свой исходный код сюда , если кому-то интересно.
Я искал не в том месте (если вам интересно посмотрите на источник, видимо avEither зацикливался). Я добился этого путем компиляции двоичного файла и запуска gdb :
Вы можете скомпилировать с флагом ghc -O0
, чтобы отключить оптимизацию, которая может показать больше имен методов.
По-видимому, Блок proc x -> do
, приведенный выше, заставлял код генерировать комбинаторы, которые вызывали метод подъема AVFunctor.arr
, который должен быть вызван - что-то там должно быть нарушает лень. Если я перепишу функцию верхнего уровня как
testAVFunctor = errorArrow "good error" >>>
isError >>> (passError ||| testAVFunctor)
, все будет работать нормально. Думаю, пора попробовать изучить и использовать garrows (аспирантом здесь, в Беркли).
Мой общий вывод из опыта состоит в том, что отладка ghci может вызывать разочарование. Например, Мне удалось сделать так, чтобы аргумент f
из AVFunctor.arr
отображался как локальная переменная, но я не могу получить от него ничего ужасно информативного:
> :i f
f :: b -> c --
Исправленный исходный код здесь