我刚开始使用Haskell并想编写一个函数,给定一个列表,返回一个列表,其中每个第二个元素都被加倍.
到目前为止,我已经想出了这个:
double_2nd :: [Int] -> [Int]
double_2nd [] = []
double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs)
Run Code Online (Sandbox Code Playgroud)
哪个有效,但我想知道你们怎么会写这个功能.是否有更常见/更好的方式或看起来对吗?
Tho*_*son 43
这还不错,以修正建议为模.一旦你对基础库更加熟悉,你可能会避免使用显式递归来支持某些更高级别的函数,例如,你可以创建一个函数列表,其中每个函数列表都是,*2并将这些函数列表应用(zip)给你的数字列表:
double = zipWith ($) (cycle [id,(*2)])
Run Code Online (Sandbox Code Playgroud)
cdk*_*cdk 20
您可以通过一些智能模式匹配来避免"空列表"异常.
double2nd (x:y:xs) = x : 2 * y : double2nd xs
double2nd a = a
Run Code Online (Sandbox Code Playgroud)
这只是以下语法糖
double2nd xss = case xss of
x:y:xs -> x : 2 * y : double2nd xs
a -> a
Run Code Online (Sandbox Code Playgroud)
模式匹配按顺序完成,因此xs将首先与模式匹配x:y:xs.然后,如果失败,catch-all模式a将成功.
ste*_*ess 10
有点神秘,但我认为这种方法对我来说非常好,并希望分享:
double2nd n = zipWith (*) n (cycle [1,2])
Run Code Online (Sandbox Code Playgroud)
zipWith接受一个函数,然后将该函数应用于两个列表中的匹配项(第一项到第一项,第二项到第二项等).函数是乘法,压缩列表是1和2的无限循环.zipWith(以及所有zip变体)在较短列表的末尾停止.
在奇数长度列表上尝试:
Prelude> double_2nd [1]
[1,*** Exception: Prelude.head: empty list
Run Code Online (Sandbox Code Playgroud)
您可以看到代码的问题。“头”和“尾”从来都不是一个好主意。