Overcoming Software

Haskell progressions

I just finished the highly recommended CIS194 course! It’s very interesting to go back to my earlier questions when I started the whole process of learning Haskell back in November or so, and compare them to my code now. I cleaned up some of the older answers, just to compare more explicitly the difference.

Old:

skips :: [a] -> [[a]]
skips [] = []
skips xs = map deIndex (map (deIndex) (flatten xs))

deIndex :: (Integral a) => [(a,b)] -> [b]
deIndex x = map snd x

flatten :: [b] -> [[(Int, (Int, b))]]
flatten xs = map dropIndex $ buildList xs

-- Drops elements in the list if they're divisible by the number.
dropIndex :: (Int,[a]) -> [(Int,a)]
dropIndex (n,xs) = filter (\(x,_) -> x `mod` n == 0) (index xs)

-- Takes a list, indexes it, expands it into a list of lists, and
-- indexes the top level list.
buildList :: [a] -> [(Int, [(Int, a)])]
buildList = index . expandList . index

-- Takes a list and converts it into a list of lists, each of which
-- is the original list.
expandList :: [a] -> [[a]]
expandList xs = map (\x -> xs) xs

-- Takes a list and indexes the items.
index :: [a] -> [(Int,a)]
index = zip [1..]

And lately:

skips :: [a] -> [[a]]
skips xs = zipWith takeEvery [1..length xs] (repeat xs)

takeEvery :: Int -> [a] -> [a]
takeEvery n xs 
    | n > length xs = []
    | otherwise     = xs !! (n-1) : takeEvery n (drop n xs)

So much cleaner! So much more elegant! It’s rather obvious that I was still thinking imperatively in November and was having a hard time grasping the functional approach.

Per Chris Allen’s learnhaskell repository, my next step is the NICTA course. I’m certainly excited to see how that progresses.