您可以几乎按照您建议的语法来编写它,如下:
lcms (a:b:c) = lcms (lcm a b:c)
lcms list = list
我觉得第二个从句有点奇怪,但并不是很糟糕:它优雅地处理了空列表,但当你知道最多只会返回一个项目时,返回列表可能被一些 Haskeller 视为在类型方面不够精确。你也可以考虑使用 Maybe
,这是经典的 0 或 1 元素类型:
lcms (a:b:c) = lcms (lcm a b:c)
lcms [answer] = Just answer
lcms [] = Nothing
另一个不错的选择是确定一个明智的基本情况。对于二进制操作,该操作的单位通常是一个不错的选择,因此对于 lcm
,我会选择1
,即:
lcms (a:b:c) = lcms (lcm a b:c)
lcms [answer] = answer
lcms [] = 1
通常情况下,尽可能避免显式递归;其他答案展示了如何采取这一步骤。在这种情况下,有一个中间转换使得基本情况稍微更加美观:不要将累加器保留在列表的头部 - 这仅仅是因为你的累加器与列表元素具有相同的类型而偶然起作用 - 可以使累积更加明确或不那么明确。因此,其中之一:
lcms (x:xs) = lcm x (lcm xs)
lcms [] = 1
lcms = go 1 where
go acc (x:xs) = go (lcm acc x) xs
go acc [] = acc
这两个实现对应于选择foldr
或foldl
来消除显式递归; foldl'
类似于第二种实现,但增加了一个seq
:
lcms = go 1 where
go acc (x:xs) = let acc' = lcm acc x in acc' `seq` go acc' xs
go acc [] = acc
foldr
,例如lcms = foldr lcm 1
。 - amar47shahfoldl
几乎永远不是你想要的。 - Daniel Wagnerfoldr
和foldl'
都可以是合理的选择,具体取决于用途。考虑到这种特定用法被类型限制为Int
--一种本质上严格的类型--我认为foldl'
是自然的选择。 - Daniel Wagner