在Haskell编程
在计算表达式时,应以什么顺序执行归约?一种常见 称为最内在评估的策略是,始终选择最内在的Redex, 不含其他redex。如果最里面的redex不止一个,按照惯例,我们选择一个 从表达式最左边的位置开始。
对表达式进行评估的另一种常见策略是对最内层的评估,始终是 选择一个最外部的Redex,因为它不包含在其他Redex中。如果超过 然后像以前一样选择一个这样的redex,它从最左边的位置开始。这并不奇怪, 这种评估策略称为最外部评估。
在函数的部分应用中,例如mult(3)(4)
,其中mult
被定义为
mult :: (Int,Int) -> Int
mult (x,y) = x * y
最里面的评估将首先将mult(3)
评估为\y->3*y
,然后评估(\y->3*y)4
。
最外部的评估如何评估mult(3)(4)
?
应用咖喱函数,例如mult'(3)(4)
,其中
mult' :: Int -> Int -> Int
mult' x = \y -> x * y
最里面的评估将首先将mult'(3)
评估为\y->3*y
,然后评估(\y->3*y)4
。
最外部的评估如何评估mult'(3)(4)
?
答案 0 :(得分:6)
唯一明智的解释方式:
mult :: (Int, Int) -> Int
mult (x,y) = x * y
在更大的问题中,是作为一元函数,该函数接受一个元组类型为(Int, Int)
的单个参数。因此,mult
不能部分应用。特别地,mult(3)
没有任何意义,因为3
不是(Int, Int)
类型的元组。
结果,无论使用最外面的缩小还是最里面的缩小,表达式mult (3,4)
的缩小在Hutton的意义上都是相同的。这里只有一个redex /应用程序,即mult
到(3,4)
的应用程序,并且最外面和最里面的减少都会导致减少:
mult (3,4)
=> 3 * 4
=> 12
对于功能:
mult' :: Int -> Int -> Int
mult' x y = x * y
或等效地:
mult' = \x -> (\y -> x * y)
表达式mult' 3 4
或等效地(mult' 3) 4
的最内层归约为:
(mult' 3) 4
= ((\x -> (\y -> x * y)) 3) 4
=> (\y -> 3 * y) 4
=> 3 * 4
=> 12
奇怪的是,最外面的减少以完全相同的方式进行:
(mult' 3) 4
= ((\x -> (\y -> x * y)) 3) 4 -- (1)
=> (\y -> 3 * y) 4
=> 3 * 4
=> 12
这是因为第(1)行中的((\x -> \y -> x * y) 3)
到4
的应用程序虽然是最外层的 application ,但它不是redex。它无法减少,因为要应用的((\x -> \y -> x * y) 3)
不是lambda表达式。 (这是lambda表达式对参数的应用。)
因此,与首次出现相反,第(1)行中只有一个redex,并且最内部和最外部的还原策略选择相同的redex。