这些表达式之间有什么区别:
z n = n + 1
和
z = \n -> n + 1
?
答案 0 :(得分:8)
第二个声明使用简单的绑定z = ...
,因此受单态性限制的影响。第一个使用函数绑定z x = ...
,因此不受影响。
除此之外,没有区别。
添加显式类型签名甚至可以消除关于单态性限制的差异,该差异不适用于任何声明。当然,如果我们使用标志或LANGUAGE
编译指示禁用GHC中的MR,则同样如此。
答案 1 :(得分:0)
没有行为上的差异,但是根据优化设置,性能可能会有细微的差异。
例如,在base
库的GHC.List
中,我们看到以下内容:
-- The lambda form turns out to be necessary to make this inline
-- when we need it to and give good performance.
{-# INLINE [0] lengthFB #-}
lengthFB :: x -> (Int -> Int) -> Int -> Int
lengthFB _ r = \ !a -> r (a + 1)
(从http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.List.html复制,但仅在base
或containers
中还有许多其他示例)。具体地说,这两种不同的形式可能在功能的多样性上有所不同并影响内联的差异。
如果定义中另外有一个where
子句,则差异可能会更加明显。在没有进行浮动优化的情况下,第二种形式意味着该函数的所有调用共享一个实例,但是在第一种形式中,不同的调用可以创建单独的实例。同样,这取决于优化设置,通常使用-O
GHC会产生相同的代码。