I'm trying to write a function that returns the longer of two strings. So far this is what I have:
maxString :: String -> String -> String
maxString a b
| (length a) > (length b) = a
| otherwise = b
This works, but I'm wondering if there is a more elegant way to write this. Note: the two arguments cannot be in a list. They must be separate arguments to allow for currying.
Thoughts?
So far all answers except Tejing's fully traverse both arguments. This one only traverses as far as the end of the shorter one.
longest a b = l' a b where
l' _ [] = a
l' [] _ = b
l' (_:ar) (_:br) = l' ar br
Played around with this one a bit. I wanted it to be a one-liner as well as having complexity O(min(n,m))
. (ie. working even with infinite lists)
maxList :: [a] -> [a] -> [a]
maxList s s' = if s == zipWith const s s' then s' else s
You can use existing Haskell facilities in Data.Ord
and Data.Function
and obtain a one-liner as follows:
maxString' x y = maximumBy (compare `on` length) [x, y]
Code:
import Data.Ord
import Data.Function
import Data.List
maxString' x y = maximumBy (compare `on` length) [x, y]
*Main> maxString' "ab" "c"
"ab"
-- EDIT --
As @DavidYoung pointed out,
compare `on` length
above can also be written in a shorter form: comparing length
That's pretty much the most concise way to write it. However, the version below will terminate even when one list is infinite (O(min(a,b)) instead of O(a + b)).
compareLengths :: [a] -> [b] -> Ordering
compareLengths [ ] [ ] = EQ
compareLengths (a:as) [ ] = GT
compareLengths [ ] (b:bs) = LT
compareLengths (a:as) (b:bs) = compareLengths as bs
maxList :: [a] -> [a] -> [a]
maxList a b = case compareLengths a b of
GT -> a
_ -> b
Also, there's no real reason to limit your function to just Strings when it would make sense for arbitrary lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With