module RwhChap4
       where

import Data.Char
import Data.List

-- page 84

-- ex. 1
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:xs) = Just x

safeTail :: [a] -> Maybe [a]
safeTail [] = Nothing
safeTail (x:xs) = Just xs

safeLast :: [a] -> Maybe a
safeLast [] = Nothing
safeLast xall@(x:xs) = Just (last xall)

safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit xall@(x:xs) = Just (init xall)

-- ex. 2
splitWith :: (a -> Bool) -> [a] -> [[a]]
splitWith _ [] = []
splitWith p xs = filter (\l -> not $ null l) $ reverse $ swHelper p xs [] []
    where
      swHelper p [] acc lst = reverse acc ++ lst
      swHelper p (x:xs) acc lst | not $ p x  = swHelper p xs [] [(reverse acc)]++lst
                                | otherwise = swHelper p xs (x:acc) lst

-- ex. 3
-- done, see file chapter-4-p84-3.hs

-- ex. 4
-- done, see file chapter-4-p84-4.hs


-- pages 97-99

-- ex. 1. done
asIntFold1 :: String -> Int
asIntFold1 = foldl (\x c -> x*10 + digitToInt c) 0

-- ex. 2. done
asIntFold2 :: String -> Int
asIntFold2 xx@(x:xs) | x == '-' = - asIntFold2 xs
                     | x == '+' || isSpace x = asIntFold2 xs
                     | otherwise = foldl (\x c -> x*10 + digitToInt c) 0 xx
-- ex. 3. done
asIntFold3 :: String -> Int
asIntFold3 xx@(x:xs) | (x == '-' || x == '+' || isSpace x) && null xs = error "Bad argument"
                     | x == '-' = - asIntFold3 xs
                     | x == '+' || isSpace x = asIntFold3 xs
                     | length xx > 9 = error "Overflow"
                     | otherwise = foldl (\x c -> x*10 + digitToInt c) 0 xx


-- ex. 4. done
data Ei = ErrMessage String
        | Intgr Int
          deriving Show
asIntEither :: String -> Ei
asIntEither xx@(x:xs) | (x == '-' || x == '+' || isSpace x) && null xs = ErrMessage "Bad argument"
                      | x == '-' = let r = asIntEither xs
                                   in
                                     case r of
                                       (Intgr i) -> Intgr (- i)
                                       _ -> r
                      | x == '+' || isSpace x = asIntEither xs
                      | length xx > 9 = ErrMessage "Overflow"
                      | otherwise = Intgr (foldl (\x c -> x*10 + digitToInt c) 0 xx)

-- ex. 5 & 6. done
concatFold :: [[a]] -> [a]
concatFold [] = []
concatFold xs = foldl (\ lst x -> lst ++ x) [] xs

-- ex. 7
takeWhileRec :: (a -> Bool) -> [a] -> [a]
takeWhileRec f [] = []
takeWhileRec f xs = reverse $ tHelper f xs []
                    where
                      tHelper fp [] lst = lst
                      tHelper fp (x:xs) lst | fp x = tHelper fp xs (x:lst)
                                            | otherwise = lst