9 haskell
我是Haskell的新手,我正在尝试一些教程.我写了这个脚本:
lucky::(Integral a)=> a-> String
lucky 7 = "LUCKY NUMBER 7"
lucky x = "Bad luck"
Run Code Online (Sandbox Code Playgroud)
我把它保存为lucky.hs并在解释器中运行它并且工作正常.
但我不确定函数定义.从我读过的小小看来,我可以同样定义幸运函数如下(函数名称为lucky2):
lucky2::(Integral a)=> a-> String
lucky2 x=(if x== 7 then "LUCKY NUMBER 7" else "Bad luck")
Run Code Online (Sandbox Code Playgroud)
两者似乎同样有效.显然,功能幸运是清晰的阅读,但是是lucky2编写一个函数以正确的方式?
Xio*_*ion 15
他们都是正确的.可以说,第一个是更惯用的Haskell,因为它使用了称为模式匹配的非常重要的特性.在这种形式中,它通常写成:
lucky::(Integral a)=> a-> String
lucky 7 = "LUCKY NUMBER 7"
lucky _ = "Bad luck"
Run Code Online (Sandbox Code Playgroud)
下划线表示您忽略参数的确切形式(值).您只关心它与7您之前的声明所捕获的模式不同.
模式匹配的重要性最好通过对更复杂的数据(例如列表)进行操作的函数来说明.例如,如果要编写计算列表长度的函数,则可能首先为空列表提供变量:
len [] = 0
Run Code Online (Sandbox Code Playgroud)
该[]子句是一个模式,设置为匹配空列表.空列表显然长度为0,所以这就是我们的函数返回.
另一部分len将是以下内容:
len (x:xs) = 1 + len xs
Run Code Online (Sandbox Code Playgroud)
在这里,你匹配模式(x:xs).冒号:是所谓的cons运算符:它将值附加到列表中.x:xs因此,表达式是一个模式,它匹配一些x附加到某个list(xs)的element ().总的来说,它匹配一个至少包含一个元素的列表,因为xs它也可以是一个空列表([]).
第二个定义len也非常简单.您计算剩余list(len xs)的长度和1 的距离,它对应于第一个元素(x).
(编写上述定义的通常方法是:
len (_:xs) = 1 + len xs
Run Code Online (Sandbox Code Playgroud)
这再次表明你不关心第一个元素是什么,只是它存在).
第三种方式是使用警卫:
lucky n
| n == 7 = "lucky"
| otherwise = "unlucky"
Run Code Online (Sandbox Code Playgroud)
没有理由对此感到困惑.总有一种方法可以做到这一点.请注意,即使没有模式匹配或防护,您也必须使用if.
到目前为止,我们所涵盖的所有形式都使用了Haskell提供的所谓的语法糖.模式保护转换为普通的案例表达式,以及多个函数子句和if表达式.因此,写这篇文章的最低级,未经处理的方式可能是:
lucky n = case n of
7 -> "lucky"
_ -> "unlucky"
Run Code Online (Sandbox Code Playgroud)
虽然你检查一下惯用的方式是好的,但我建议初学者使用对他来说最好的东西,无论他最了解什么.例如,如果一个(尚未)理解点自由风格,则没有理由强制它.它迟早会来找你.