{- |
Description: Length of a list
Copyright: Copyright (C) 2021 Yoo Chung
License: GPL-3.0-or-later
Maintainer: dev@chungyc.org

Some solutions to "Problems.P04" of Ninety-Nine Haskell "Problems".
-}
module Solutions.P04 (myLength, myLength', myLength'', myLength''') where

-- | Find the number of elements of a list.
--
-- Add 1 for each element by induction.
myLength :: [a] -> Int
myLength :: forall a. [a] -> Int
myLength []     = Int
0
myLength (a
_:[a]
xs) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [a] -> Int
forall a. [a] -> Int
myLength [a]
xs

-- | Find the number of elements of a list.
--
-- Cheat by using 'length'.
myLength' :: [a] -> Int
myLength' :: forall a. [a] -> Int
myLength' = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length

-- | Find the number of elements of a list.
--
-- Map elements to 1 and return their sum.
myLength'' :: [a] -> Int
myLength'' :: forall a. [a] -> Int
myLength'' [a]
l = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (a -> Int) -> [a] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> a -> Int
forall a b. a -> b -> a
const Int
1) [a]
l

-- | Find the number of elements of a list.
--
-- Add 1 for each element by induction, but tail recursively.
myLength''' :: [a] -> Int
myLength''' :: forall a. [a] -> Int
myLength''' [a]
l = [a] -> Int -> Int
forall {t} {a}. Num t => [a] -> t -> t
accumulate [a]
l Int
0
  where accumulate :: [a] -> t -> t
accumulate [] t
n     = t
n
        accumulate (a
_:[a]
xs) t
n = [a] -> t -> t
accumulate [a]
xs (t
nt -> t -> t
forall a. Num a => a -> a -> a
+t
1)