Для чего бы то ни было, на самом деле здесь есть два вида «отладки»:
- Регистрация промежуточных значений, таких как значение, которое конкретное подвыражение имеет при каждом вызове, в рекурсивную функцию
- Проверка поведения во время выполнения вычисления выражения
На строгом императивном языке они обычно совпадают. В Хаскеле они часто не делают:
- Запись промежуточных значений может изменить поведение среды выполнения, например, путем принудительного вычисления терминов, которые в противном случае были бы отброшены.
- Фактический процесс вычислений может существенно отличаться от кажущейся структуры выражения из-за лени и общих подвыражений.
Если вы просто хотите вести журнал промежуточных значений, есть много способов сделать это - например, вместо того, чтобы поднимать все в IO
, будет достаточно простой монады Writer
, что эквивалентно созданию функции возвращают 2 кортежа их фактического результата и значения аккумулятора (как правило, своего рода список).
Также обычно нет необходимости помещать все в монаду, только те функции, которые необходимо записать в значение "log" - например, вы можете выделить только те подвыражения, которые могут понадобиться ведите журналирование, оставляя основную логику чистой, затем заново собирайте все вычисления, комбинируя чистые функции и журналируя вычисления обычным образом с fmap
s и еще много чего. Имейте в виду, что Writer
является своего рода извинительным оправданием для монады: без возможности читать из журнала, только записывать в него, каждое вычисление логически не зависит от его контекста, что облегчает его жонглировать вещами.
Но в некоторых случаях даже это излишне - для многих чистых функций достаточно просто переместить подвыражения на верхний уровень и попробовать что-то в REPL.
Однако, если вы хотите на самом деле проверить поведение чистого кода во время выполнения - например, чтобы выяснить, почему подвыражение расходится - в общем случае нет способа сделать это из другого чистого кода - на самом деле это, по сути, определение чистоты. Таким образом, в этом случае у вас нет выбора, кроме как использовать инструменты, которые существуют «вне» чистого языка: либо нечистые функции, такие как unsafePerformPrintfDebugging
- errr, я имею в виду trace
-, либо модифицированную среду выполнения, такую как GHCi отладчик.