首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >关于评估顺序

关于评估顺序
EN

Stack Overflow用户
提问于 2018-09-23 07:41:21
回答 2查看 200关注 0票数 0
代码语言:javascript
复制
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将使用?

仍然是函数式编程的新手,所以我不确定我的“惰性计算”过程是否正确。

EN

回答 2

Stack Overflow用户

发布于 2018-09-23 17:21:58

您可以通过将子表达式替换为(error "x")(error "y")等来测试您的假设。首先评估的错误是在您运行表达式时出现的错误。

票数 3
EN

Stack Overflow用户

发布于 2018-09-24 00:12:29

就这一点而言,只要得到正确的答案,求值就可以按照编译器希望的任何顺序进行。例如,它可以将整个表达式优化为23,并且在运行时根本没有求值。它可以先计算右侧算术运算符,然后再计算左侧运算符,减法除外。它可以在运行时随机决定首先评估哪一个。

忽略这一点,有关如何手动完成这项工作的解释,请参阅"How Lazy Evaluation Works in Haskell"

但是如何手动解决这个问题并不是这个答案的重点。您的问题是Haskell实际上会使用什么求值顺序,所以这个答案大概是告诉您程序在使用您选择的编译器进行编译时所使用的求值顺序(忽略一些对基本理解求值顺序不重要的注意事项)。

通过一些工作,我们可以让Haskell告诉我们它的计算顺序。如果你在学校,你可能想学习如何在没有帮助的情况下手动查找评估顺序,这样你就可以在测试中取得好成绩。

建议您仅在检查您有信心的答案时才执行此操作。如果你被卡住了,你也可以使用它,但你应该只读到你卡住了的地方,看看下一步是什么,并对为什么是下一步做出有根据的猜测,这样你就可以开始通过实验来了解规则是什么。这与上面的链接文章相结合,将会有相当大的帮助。

为此,我们可以通过使用Debug.Trace的函数而不是error来扩展Jonas Dureg&rd的答案。Debug.Trace的函数可以在开始或停止计算时输出结果,所以它们在这里非常合适:

代码语言:javascript
复制
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)

一旦你在纸上解决了问题,你可以用the results of the above code run on GHC检查你的答案。它告诉您使用GHC编译时您的代码使用的评估顺序。

您也可以选择通过您选择的Haskell编译器来运行它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52461791

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档