I've decided to learn Haskell by following the current Coursera algorithms course using Haskell to implement the algorithms discussed.
First up is merge sort, which I've implemented as shown here. I'm brand new to Haskell so looking for any suggestions for improvements to the code - it seems quite verbose - and pointers on anything I may be doing wrong or in a weird way because I don't know what I'm doing.
module Main where
import System.Environment
main :: IO ()
main = do
args <- getArgs
mapM_ putStrLn $ sort args
sort :: (Ord a) => [a] -> [a]
sort xs = reduce True $ map (arr) xs
arr :: a -> [a]
arr x = [x]
reduce :: (Ord a) => Bool -> [[a]] -> [a]
reduce _ [] = []
reduce forwards (x:[]) = if forwards then x else reverse x
reduce forwards xs = reduce (not forwards) (combine forwards [] xs)
combine :: (Ord a) => Bool -> [[a]] -> [[a]] -> [[a]]
combine forwards acc [] = acc
combine forwards acc (x:[]) = (reverse x):acc
combine forwards acc (x:y:zs) = let merged = merge forwards x y
acc' = merged:acc
in combine forwards acc' zs
merge :: (Ord a) => Bool -> [a] -> [a] -> [a]
merge forwards xs ys = mergeIter forwards [] xs ys
mergeIter :: (Ord a) => Bool -> [a] -> [a] -> [a] -> [a]
mergeIter _ acc [] [] = acc
mergeIter forwards acc (x:xs) [] = mergeIter forwards (x:acc) xs []
mergeIter forwards acc [] (y:ys) = mergeIter forwards (y:acc) [] ys
mergeIter forwards acc (x:xs) (y:ys)
| x <= y && forwards = mergeIter forwards (x:acc) xs (y:ys)
| x > y && not forwards = mergeIter forwards (x:acc) xs (y:ys)
| otherwise = mergeIter forwards (y:acc) (x:xs) ys
One specific question I have is around recursive function with accumulator arguments - you'll see in the listing that I've had to create a mergeIter
function just to allow a default for the initial argument for the accumulator.
As far as I can see Haskell doesn't support default values for arguments - should I be doing something else instead? A fold maybe?