我总是以这种格式编写生成列表的递归函数:
recursiveFunc :: [a] -> [b]
recursiveFunc (x:xs) = [change x] ++ resursiveFunc xs where
change :: a -> b
change x = ...
我意识到上述任何功能都可以针对a -> b
案例编写,然后只需map
编写一组[a]
,但请以此淡化情况为例
HLint建议将[change x] ++ recursiveFunc xs
替换为change x : recursiveFunc xs
。
这个建议纯粹是审美的,还是对Haskell如何执行该功能有一些影响?
答案 0 :(得分:9)
使用[change x] ++ recursiveFunc xs
时,您会创建一个多余的单元素列表,然后由++
函数拆分。使用未发生的:
。
Plus ++
是一个函数,然后使用:
构造函数。直接使用:
时,无需调用函数。
因此,使用:
在理论上更有效率(编译器可能会优化这些差异)。
答案 1 :(得分:4)
主要优点是change x : blah
更清晰 - (:)
正是您要做的事情(将一个元素添加到列表中)。为什么要在一个人做的时候调用两个函数?
建议的方式也略微提高效率 - 您的方式创建一个单元素列表然后将其抛弃并用不同的列表链接替换它。另一种方法只是创建一个列表链接。也就是说,差异很小,99%的时间都不重要。
答案 2 :(得分:4)
该行
recursiveFunc (x:xs) = [change x] ++ resursiveFunc xs
有点令人困惑,因为它不是正常形式。这意味着++
可以直接替换为其定义的右侧:
(++) (a:as) bs = a:((++) as bs)
(++) [] bs = bs
-- =>
recursiveFunc (x:xs) = (change x):((++) [] resursiveFunc xs)
-- =>
recursiveFunc (x:xs) = (change x):(resursiveFunc xs)
Haskell编译器会自动应用此类转换。
但是因为它是如此微不足道,它使你的代码更难阅读。一个人看着它并问“等等......什么?”