You can write it with almost the syntax you suggested, thus:
lcms (a:b:c) = lcms (lcm a b:c)
lcms list = list
I find the second clause a little bit odd, but not terrible: it gracefully handles empty lists, though returning a list when you know you will return at most one item might be seen by some hasochists as being a bit imprecise with your types. You could also consider using Maybe
, the canonical 0-or-1 element type:
lcms (a:b:c) = lcms (lcm a b:c)
lcms [answer] = Just answer
lcms [] = Nothing
Another good choice would be to identify a sane base case. For binary operations, the unit of the operation is usually a good choice, so for lcm
, I would choose 1
, thus:
lcms (a:b:c) = lcms (lcm a b:c)
lcms [answer] = answer
lcms [] = 1
Generally, one tries to avoid explicit recursion when possible; the other answer shows how to take that step. In this case, there is an intermediate transformation that makes the base cases slightly more aesthetically pleasing: instead of keeping your accumulator at the head of the list -- which only incidentally works because your accumulator is the same type as the list elements -- one can make the accumulation more explicit or less. Thus, one of these:
lcms (x:xs) = lcm x (lcm xs)
lcms [] = 1
-- OR
lcms = go 1 where
go acc (x:xs) = go (lcm acc x) xs
go acc [] = acc
These two implementations correspond to choosing foldr
or foldl
for eliminating the explicit recursion; foldl'
would be similar to the second one, but with an extra seq
:
lcms = go 1 where
go acc (x:xs) = let acc' = lcm acc x in acc' `seq` go acc' xs
go acc [] = acc