Q:

Is there a more clean, elegant, Haskell way to write this LCM function?

I'm just starting out with Haskell and hammered out this simple recursive algo to find the LCM for every number in a list. It works, but it's messy and I was hoping for some peer-review on how to make this more elegant, readable, and Haskell-y.
lcms list 
  | length list > 1 = lcms (lcm (head list) (head (tail list)):(tail (tail list)))
  | otherwise = list

So that takes a list and does LCM of the first two items, then prepends it to list minus those two elements. Basically, the psudocode I'm going for is like this:
lcms [a,b,c] = lcm (a, (lcm (b, c))

Any suggestions, anyone? I'm eager to improve at Haskell and write things that people can actually read. Efficiency tips are welcome too!
Thanks, all!

A:

It's a fold:
import Data.List

lcms :: [Int] -> Int
lcms xs = foldl' lcm 1 xs

where lcm compute the lcm of just two numbers:
lcm :: Int -> Int -> Int

A:

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

