为什么Haskell Prelude中的null函数定义如此奇怪?

Leo*_* Ge 6 haskell functional-programming compiler-optimization

Preludenull函数的定义如下:

null             :: [a] -> Bool
null []          =  True
null (_:_)       =  False
Run Code Online (Sandbox Code Playgroud)

令我困惑的是定义的第三行,为什么写:

null(_:_)        = False
Run Code Online (Sandbox Code Playgroud)

代替:

null any = False
Run Code Online (Sandbox Code Playgroud)

它与编译器优化有什么关系吗?

Wil*_*sem 5

它与编译器优化有什么关系吗?

不,实际上可以说写入null (_:_)效率低于null any(如果编译器没有对此进行优化),因为现在你要求Haskell验证它确实是"缺点".虽然如果编译器对数据类型进行一些簿记,但当然很容易对其进行优化.据我所知,大多数编译器ghc以及几乎所有不是由三岁孩子编写的编译器都会这样做.

首先,最好不要写一个wilcard _(或命名any),因为列表的定义(以及任何其他数据类型可能会改变).虽然列表的可能性很小,但有人可能会重新定义列表.例如:

data [a] = [] | (a:[a]) | (Int///[a])
Run Code Online (Sandbox Code Playgroud)

例如,后一种模式意味着该列表重复多次.在这种情况下,一个不是由三岁孩子写编译器会警告说不完整的模式null:它会因此声称(_///_)没有指定模式.然而,如果您使用通配符,它​​将回退到null any案例.

一般来说,最好小心使用通配符:只有在你真的不关心函数的内容时,才应该使用通配符.

  • 它的效率不高*.编译器*总是*优化它. (4认同)
  • @dfeuer:这是一个奇怪的主张,因为没有提到具体的编译器.我可以在前几天编写一个不执行此操作的Haskell编译器.我的主张并不是说好的编译器不能优化它.这个想法只是在语法上,前者效率较低.:) (2认同)