Относительно порядка оценки - PullRequest
0 голосов
/ 23 сентября 2018
multiply :: Int -> Int -> Int 
multiply a b = a * b 

minus :: Int -> Int -> Int 
minus a b = a - b 

minus2 :: Int -> Int -> Int 
minus2 a b = b – a


minus2 (multiply (minus 3 5) 7) 9
minus2 ((minus 3 5) * 7) 9
9 - ((minus 3 5) * 7)
9 - ((3 - 5) * 7)
9 - ((-2) * 7)
9 - (-14)
23

Запуск строки minus2 (multiply (minus 3 5) 7) 9 У меня есть правильный порядок оценки, который Haskell будет использовать?

Все еще новичок в функциональном программировании, поэтому я не уверен, что у меня "ленивая оценка"процесс правильный.

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

В сущности, оценка может продолжаться в любом порядке, необходимом компилятору, если только он получает правильный ответ.Например, он может оптимизировать все выражение до 23 и вообще не иметь оценки во время выполнения.Он может оценивать правую часть арифметических операторов перед левой, кроме вычитания.Во время выполнения он мог бы произвольно решить, какую оценку сначала выполнить.

Игнорирование этого для объяснения того, как вручную выполнять работу, см. «Как работает отложенная оценка в Haskell» .


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

С некоторой работой мы можем попросить Haskell сообщить нам, в каком порядке она оценивает. Если вы учитесь в школе, вы, вероятно, захотите научиться находить порядок оценки вручную без посторонней помощи, чтобы вы могли справиться с задачей.тест.

Рекомендуется делать это только для проверки ответа, в котором вы уверены. Вы также можете использовать его, если застряли, но вы должны читать только до того момента, когда застряличтобы увидеть, каков следующий шаг, и сделать обоснованное предположение о , почему это следующий шаг, чтобы вы могли начать изучать, каковы правила, экспериментируя.Это, в сочетании с вышеупомянутой связанной статьей, очень поможет.

Чтобы сделать это, мы можем расширить ответ Джонаса Дюрегора, используя функции Debug.Trace вместо error.Функции Debug.Trace могут выводить вещи , когда что-то начинает или останавливает оценку, поэтому они вполне уместны здесь:

import Debug.Trace

-- Show result
r :: String -> Int -> Int
r nm n = trace ("Result of " ++ nm ++ " is " ++ show n) n

-- Show evaluation of Int -> Int -> Int function
f :: String -> (Int -> Int -> Int) -> Int -> Int -> Int
f nm g a b = e nm $ g a b

-- Show evaluation of an Int
e :: String -> Int -> Int
e nm = r nm . trace ("Evaluating " ++ nm)

-- Show Int literal
i :: Int -> Int
i n = e (show n) n

multiply :: Int -> Int -> Int
multiply a b = e "multiply" $ (f "multiply's *" (*))
                              (e "multiply's a" a)
                              (e "multiply's b" b)

minus :: Int -> Int -> Int
minus a b = e "minus" $ (f "minus's -" (-))
                        (e "minus's a" a)
                        (e "minus's b" b)

minus2 :: Int -> Int -> Int
minus2 a b = e "minus2" $ (f "minus2's -" (-))
                          (e "minus2's b" b)
                          (e "minus2's a" a)

main :: IO ()
main = print $ minus2 (multiply (minus (i 3) (i 5)) (i 7)) (i 9)

Как только вы решили проблему на бумаге,Вы можете проверить свой ответ с помощью результатов выполнения приведенного выше кода на GHC .Он сообщает вам, какой порядок оценки использует ваш код при компиляции с GHC.

Вы также можете запустить его через выбранный вами компилятор Haskell.

0 голосов
/ 23 сентября 2018

Вы можете проверить свою гипотезу, заменив подвыражения на (error "x"), (error "y") и т. Д. В зависимости от того, какая ошибка будет оценена первой, она будет отображена при запуске выражения.

...