Useful, Cool, Magical Idioms

this collection is supposed to be comprised of short, useful, cool, magical examples, which incite curiosity in the reader and (hopefully) lead him to a deeper understanding of advanced haskell concepts. at a later time i might add explanations to the more obscure solutions. i've also started providing several alternatives to give more insight into the interrelations of solutions.

whoever has any more ideas, please feel free to just add them; if you see mistakes or simpler solutions please correct my chaotic collection. i'm very interested in more "obscure" solutions, which showcase the applicability of haskell's (unique) features (i.e. monad magic, folds and unfolds, fix points, ...)

-- splitting in twos (alternating)
-- "1234567" -> ("1357", "246")
foldr (\a (x,y) -> (a:y,x)) ([],[])

-- splitting in N
-- 2 -> "1234567" -> ["12", "34", "56", "7"]
List.unfoldr (\a -> if null a then Nothing else Just \$ splitAt 2 a) "1234567"
fst . until (null . snd) (\(a,b) -> let (x,y) = splitAt 2 b in (a++[x],y)) \$ ([], "1234567")

-- split at whitespace
-- "hello world" -> ["hello","world"]
words
fst . until (null . snd)
(\(a,b) -> let (x,y) = break (==' ') b
in (a++[x], drop 1 y))
\$ ([], "hello world")

-- combinations
-- "12" -> "45" -> ["14", "15", "24", "25"]
sequence ["12", "45"]
[x:[y] | x <- "12", y <- "45"]
"12" >>= \a -> "45" >>= \b -> return (a:[b])

-- factorial
-- 6 -> 720
product [1..6]
foldl1 (*) [1..6]
(!!6) \$ unfoldr (\(n,f) -> Just (f, (n+1,f*n))) (1,1)
fix (\f (n,g) -> if n <= 0 then g else f (n-1,g*n)) (6,1)

-- interspersing with newlines
-- ["hello","world"] -> "hello world"
unlines
intersperse '\n'

-- sorting by a custom function
-- length -> ["abc", "ab", "a"] -> ["a", "ab", "abc"]
sortBy length
map snd . sortBy fst . map (length &&& id)

-- zweierpotenzen
iterate (*2) 1
unfoldr (\z -> Just (z,2*z)) 1

-- simulating lisp's cond
case () of () | 1 > 2     -> True
| 3 < 4     -> False
| otherwise -> True

-- add indices to list for later use
-- [3,3,3] -> [(0,3),(1,3),(2,3)]
zip [0..]

-- fibonacci series
unfoldr (\(f1,f2) -> Just (f1,(f2,f1+f2))) (0,1)
fibs = 0:1:zipWith (+) fibs (tail fibs)
fib = 0:scanl (+) 1 fib

-- unjust'ify list of Maybe's
-- [Just 4, Nothing, Just 3] -> [4,3]
catMaybes

-- find substring
-- "ell" -> "hello" -> True
substr a b = any (a `elem`) \$ map inits (tails b)

-- apply a list of functions to an argument
-- even -> odd -> 4 -> [True,False]
map (\$4) [even,odd]
sequence [even,odd] 4

-- apply a function to two other function the same argument
-- (lifting to the function monad (->))
-- even 4 && odd 4 -> False
liftM2 (&&) even odd 4
liftM2 (>>) putStrLn return "hello"    -- putStrLn "hello" >> return "hello"

-- match a constructor
-- this is better than applying all the arguments, because this way the data type can be changed without touching the code (ideally).
case a of Just{} -> True
_      -> False

-- prime numbers
-- example of a memoising caf (??)
primes = sieve [2..] where
sieve (p:x) = p : sieve [ n | n <- x, n `mod` p > 0 ]
{-
either
maybe
group