繁体   English   中英

Haskell最好的风格是什么

[英]What's the best style in Haskell

感谢Erik Meijer的演讲,也取得了重大进展。 好手表,也许暗示。 Haskell允许使用几种方法来编写相同的函数。 就效率和可读性而言,哪一个最好?

sqr' = \x -> x * x
sqr'' x = x * x
sqr''' = (^2)

在这两个顶级定义之间:

sqr' = \x -> x * x
sqr'' x = x * x

第二个在Haskell程序中几乎是普遍首选的。 搜索几乎所有现实世界中的Haskell代码块,您会发现第二个示例很多,但第一个示例很少。 相反,“ lambda抽象”(即\\x -> ...语法)最常用于定义匿名函数,以将其作为参数传递给高阶函数。

选择第二种语法有两个原因。 首先,从字面上看,它更加简洁,从可读性的角度来看,它包含更少的不同语法元素(即并置和=运算符,而不是并置=\\-> )。 它还很好地概括了使用多个模式定义函数的常见Haskell习惯用法:

factorial 0 = 1
factorial n | n > 0 = n * factorial (n-1)

要使用lambda语法执行此操作,您需要添加一个显式的case构造,其中涉及一套语法元素。

之间:

sqr'' x = x * x
sqr''' = (^2)

或者-也许是更公平的比较:

sqr'''' x = x^2
sqr''' = (^2)

这更多是个人喜好问题。 许多Haskell程序员喜欢所谓的无语法的外观,其中较大的函数是使用高阶函数和/或没有明确参数的组合函数链组成的,例如:

mostFrequentWord
   = head . maximumBy (comparing length) . group . sort . words

sqr'''类的定义更符合这种总体风格。

就这些形式之间的含义差异而言,实际上有点复杂。 如果您采用以下模块,则出于晦涩的原因,它们与称为“单态性限制”和“默认规则”的事情有关:

module Square where
sqr' = \x -> x * x
sqr'' x = x * x
sqr''' = (^2)

并用ghc -O编译, sqr'sqr'''的定义是等效的-两者都将专门用于Integer类型,并且将生成完全相同的代码。 (使用GHC 8.0.2测试)。 相反, sqr''保持多态性并带有签名Num a => a -> a sqr'' Num a => a -> a ,这意味着它可以对任何数字类型进行操作。

如果添加顶级类型签名(无论如何,都是好的做法!),如下所示:

module Square where
sqr', sqr'', sqr''' :: (Num a) => a -> a
sqr' = \x -> x * x
sqr'' x = x * x
sqr''' = (^2)

然后它们都生成完全相同的代码。 您可以使用以下方法查看生成的“核心”(编译器在编译过程中创建的中间点,类似于Haskell的中间语言),从而自己验证这一点:

ghc -O -ddump-simpl -dsuppress-all -fforce-recomp Square.hs

在生成的核心中,您将看到定义:

sqr' = \ @ a_aBC $dNum_aLW x_arx -> * $dNum_aLW x_arx x_arx

看起来很奇怪,但从根本上说,将适当的Num类型的*操作应用于参数x_arx x_arx 为两个变体生成的代码:

sqr'' = sqr'
sqr''' = sqr'

表明GHC认为它们和sqr'之间没有区别,因此在语义或性能上也没有区别。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM