99 problems in Haskell
explanations to the solutions of 99 problems in Haskell

Problem 1 - Find Last Element

myLast = foldr1 (const id)
myLast = foldr1 (flip id)
myLast = foldl1 (curry snd)

Problem 2 - Find Last but One Element

myButLast (x:(_:[])) = x
myButLast (_:xs) = myButLast xs
myButLast = (!! 1) . reverse
lastbut1 :: Foldable f => f a -> a
lastbut1 = fst . foldl (\(a,b) x -> (b,x)) (err1,err2)
  where
    err1 = error "lastbut1: Empty list"
    err2 = error "lastbut1: Singleton"

Problem 3 - Find the kth element of a list

elementAt xs n 
  | length xs < n = error "Index out of bounds"
  | otherwise = fst . last $ zip xs [1..n] 
elementAt xs n = head $ foldr ($) xs 
                         $ replicate (n - 1) tail
elementAt xs n 
  | length xs < n = error "Index out of bounds"
  | otherwise = head $ drop (n - 1) xs
elementAt_w'pf = (last .) . take . (+1)

:t (.) :: (b -> c) -> (a -> b) -> a -> c

:t (take . (+1)) :: Int -> [a] -> [a]
:t (last .) :: (a -> [c]) -> a -> c
-- :t last :: [c] -> c
-- looking for a function that takes in a list and returns the last element

-- take . (+1) being the second function composed
-- returns a function that takes a list and returns a list
-- curried function
-- (a -> b) = Int -> ([a] -> [a])

-- last . being the first function composed
-- takes from the second function that type parameter a is [a] and c is a
-- takes in a second function, takes in a list and returns the last emement
-- curried function again
-- (b -> c) = ([a] -> [a]) -> ([a] -> a)

-- a -> c = Int -> ([a] -> a)

:t (last .) . (take . (+1)) :: Int -> [a] -> a

-- (take . (+1)) doesn't return a list so we cannot compose it was last directly
-- instead it returns a function that returns a list
-- hence when we can compose it with last . since that is looking for a function that returns a list

Problem 4 - Find number of elements in the list

myLength = foldr (const (+1)) 0 xs
-- 1 is added first to the accumulator then const against the next value
foldl (const . (+1)) 0 x

-- note that
foldl (const (+1)) 0 xs
-- returns last element + 1
-- (+1) is returned and applied to the next value