Как напечатать переменную внутри функции? - PullRequest
0 голосов
/ 28 июня 2018

У меня есть функция:

fold_wrap :: (a -> a -> a) -> (Prop -> a) -> a -> Wrapper -> a

fold_wrap v x z (Mrappe l r)   = v ( v(v x z l) v(v x z r) )
fold_wrap v x z (Wrap f)       = x f 
fold_warp v x z (Wtail )       = z

Где я сталкиваюсь со следующей ошибкой:

mast: mast.hs:(15,1)-(16,31): Non-exhaustive patterns in function fold_mast

Итак, я добавил

fold_wrap v x z _ = z 

Который исправил ошибку, но

Что заставило меня поверить, что некоторые образцы действительно остались бесподобными.

Теперь моя интуиция исправить это состояла в том, чтобы напечатать то, что передается функции.

Итак, я добавил это

fold_wrap  v x z g = print g

Но это тоже не сработало, поскольку функция должна возвращать тип a, а не IO

Итак, мой вопрос:

Как мне напечатать g и вернуть несколько фиктивных значений одновременно?

Советы по исправлению этого неполного соответствия шаблонам также приветствуются.

1 Ответ

0 голосов
/ 28 июня 2018

Я не могу говорить с вашей неисчерпывающей проблемой шаблонов, не видя определения Wrapper, которое вы используете. Однако я могу ответить на вопрос, который вы задали.

Обычно в Haskell для вывода значения нам нужно иметь IO в нашем типе возврата. Это обеспечивает чистоту функциональности кода и дает нам массу преимуществ, поэтому мы никогда не должны пытаться нарушать это правило в рабочем коде.

Однако , в вашей голове всегда есть тот противный маленький голос, который хочет напечатать значение только для целей отладки. Имейте в виду, что это никогда не должно быть сделано в готовом продукте; это только по причинам отладки. Однако по этой причине Haskell предоставляет модуль Debug.Trace, который нарушает все нормальные и нормальные функциональные правила, чтобы позволить вам сделать это.

import Debug.Trace

fold_wrap v x z g = traceShow g someDummyValue

Теперь есть несколько соображений. Во-первых, Wrapper все еще должен иметь Show. Мы ничего не можем с этим поделать; если Haskell не знает , как напечатать что-либо, то он не сможет напечатать это даже для отладки. Во-вторых, Haskell не является строгим, поэтому при запуске кода необходимо убедиться, что вызов fold_wrap действительно оценен. Просто вызвать его и связать результат с фиктивной переменной не подойдет; вам нужно на самом деле взять это фиктивное значение и использовать его в каком-то контексте, где оно абсолютно необходимо оценить, обычно распечатывая его в main.

Я говорил это раньше, но я скажу это снова, потому что это важно. Debug.Trace равно только для отладки . Это может вызвать привыкание, особенно если вы новичок в Haskell. Но не использует этот модуль в производственном коде. У него много проблем, таких как не гарантирование порядка печати, которые не имеют значения при отладке, но имеют значение много при использовании в пользовательском коде. Не говоря уже о том, что оно нарушает все правила Хаскелла в книге.

...