Prelude> :m +Data.List
Prelude Data.List> :m +Data.Function
Prelude Data.List Data.Function> minimumBy (compare`on`length) [[1,2,9],[3,4],[1,2,3,5]]
[3,4]
How it works – well, minimum
is quite obvious. But we don't want to compare the number lists by the default lexicographical ordering, rather we want to specify what property exactly is compared – namely, the length. compare`on`ᴘʀᴏᴘᴇʀᴛʏ
is a simple-to memorise general trick to do that, it uses
Data.Function.on :: (b->b->c) -> (a->b) -> a->a->c
compare :: Ord a => a -> a -> Ordering
so (compare`on`)
is Ord b => (a->b) -> a->a->Ordering
, i.e. we get a comparison function for any data type if we can supply a function that yields a comparable property. In our case, that is length
.
Finally, we need to use that ordering for actually selecting the minimum element. The function that does the trick is Data.List.minimumBy
.
Note that this solution isn't really efficient: it will apply length
more that once to each list. You shouldn't use it for finding the shortest list amongs many thousands, with hundreds of elements each. There exist of course better algorithms, but they aren't as easy and concise.