module Playground01 where

import Data.List

simple :: t -> t
simple x = x

calcChange :: (Num t, Ord t) => t -> t -> t
calcChange owed given = if change > 0 
                        then change 
                        else 0 
                        where change = given - owed

doublePlusTwo :: Num t => t -> t
doublePlusTwo x = doubleX + 2
    where doubleX = x * 2

yorga :: Integer
yorga = 9

doubleMe :: Num a => a -> a
doubleMe x = x * 2

-- (\x -> x) "hi" 

body :: Ord t => t -> t -> t
body sumSquare squareSum = if sumSquare > squareSum 
                            then sumSquare 
                            else squareSum 

body' ::  Ord a => a -> a -> a
body' = (\sumSquare squareSum  ->  
                            if sumSquare > squareSum 
                            then sumSquare 
                            else squareSum) 

body'' :: Num a => a -> a -> a
body'' = (\x y -> x + y) 

body''' :: Num a => a -> a -> a
body''' x y = x + y

sumSquareOrSquareSum :: (Ord a, Num a) => a -> a -> a
sumSquareOrSquareSum x y = body' (x^2 + y^2) ((x+y)^2)

sumSquareOrSquareSum' :: (Num t, Ord t) => t -> t -> t
sumSquareOrSquareSum' x y = let sumSquare = (x^2 + y^2)
                                squareSum = ((x+y)^2)
                            in
                                if sumSquare > squareSum
                                    then sumSquare
                                    else squareSum

overwrite :: Num t => t1 -> t
overwrite x =   let x = 2 
                in  
                    let x = 3 
                    in 
                        let x = 4 
                        in  
                        x                                     

k :: Integer
k = 10

add :: Integer -> Integer
add y = y + k

add' :: Num a => a -> a
add' y = (\k -> y + k) 3

add'' :: Num a => t -> a
add'' y = (\y -> 
                (\k -> y + k ) 1
                    ) 2

--Q2.2

counter :: Num a => t -> a
counter x = let x = x + 1
                in
                    let x = x + 1
                    in
                        x

counter' :: Num a => a -> a
counter' x = (\x -> x + 1) x

counter'' :: Num a => a -> a
counter'' x = (\x -> 
                    (\x -> x + 1) x + 1
                    ) x

--listing 3.3

ifEven :: Integral t => (t -> t) -> t -> t
ifEven myFunction x = if even x
                        then myFunction x
                        else x

inc :: Num a => a -> a
inc n = n + 1

double :: Num a => a -> a
double n = n * 2

square :: Num a => a -> a
square n = n ^ 2

ifEvenInc :: Integral t => t -> t
ifEvenInc n = ifEven inc n

ifEvenDouble :: Integral t => t -> t
ifEvenDouble n = ifEven double n

ifEvenSquare :: Integral t => t -> t
ifEvenSquare n = ifEven square n

--esempio con la lambda
ifEvenLambaDouble :: Integral k => k -> k
ifEvenLambaDouble k' = ifEven (\x -> x * 2) k'

--QUICK CHECK 3.1 Write a lambda function for cubing x and pass it to ifEven

ifEvenLambaCube :: Integral a => a -> a
ifEvenLambaCube k' = ifEven (\x -> x ^ 3) k'

--listing 3.4

names :: [([Char], [Char])]
names = [("Ian", "Curtis"),
        ("Bernard","Sumner"),
        ("Peter", "Hook"),
        ("Stephen","Morris")]

-- Listing 3.4 names
sortedNames :: [(String, String)]
sortedNames = sort names

-- lastNamesComparator :: Ord(a,a) => a -> a -> Ordering
lastNamesComparator :: Ord a1 => (a2, a1) -> (a, a1) -> Ordering
--lastNamesComparator :: Ord a1 => ((a2, a1), (a, a1)) -> Ordering
lastNamesComparator  name1 name2 =
                                let lastName1 = snd name1
                                in
                                let lastName2 = snd name2
                                in
                                if lastName1 > lastName2
                                then GT
                                    else if lastName1 < lastName2 
                                        then LT
                                        else EQ

-- Listing 3.5 compareLastNames
compareLastNames :: Ord a1 => (a2, a1) -> (a, a1) -> Ordering
compareLastNames name1 name2 = if lastName1 > lastName2
    then GT
    else if lastName1 < lastName2
    then LT
    else EQ
    where   lastName1 = snd name1
            lastName2 = snd name2

-- esempio
-- compareLastNames ((\n -> head n) names) ((\n ->  head n) names)
-- uso
-- sortBy compareLastNames names

-- QUICK CHECK 3.2 In compareLastNames
-- you didn’t handle the case of having two last names that are the same
-- but with different first names. Modify the compareLastNamesfunction to compare first names and use it to fix
-- compareLastNames.

compareLastNames' :: Ord a => ([a], [a]) -> ([a], [a]) -> Ordering
compareLastNames' name1 name2 = if complexName1 > complexName2
    then GT
    else if complexName1 < complexName2
    then LT
    else EQ
    where   lastName1 = snd name1
            lastName2 = snd name2
            firstName1 = fst name1
            firstName2 = fst name2
            complexName1 = lastName1 ++ firstName1
            complexName2 = lastName2 ++ firstName2
