-----------------------------------------------------------------------------
-- |
-- Module      : Chapter03
-- Description : Types and Entities
--
-- Copyright   : (c) Eric Zoerner, 2023
-- License     : BSD3
-- Maintainer  : eric.zoerner@proton.me
--
-----------------------------------------------------------------------------

module Chapter03 where

------------------
-- * Exercise 3.1
------------------
{- $ex31
__(a)__ @(False || (True && False)) || True@

>:: Bool

__(b)__ @((2 / 3) / 4) == ((4 / 3) /2)@

>:: Bool

__(c)__ @((7 - (5 / 4)) > 6) || (((2 ^ 5) - 1) == 31)@

>:: Bool

__(d)__ @2 < 3 < 4@

/Not well formed: cannot operate on Bool with comparison operators./

__(e)__ @(2 < 3) || (3 < 4)@

>:: Bool

__(f)__ @2 && 3 < 4@

/Not well formed: cannot operate on numeric types with logical && operator./
-}

------------------
-- * Exercise 3.2
------------------

-- | @f(x) = { 0, x ≤ 0; x, x > 0}@
f :: Double -> Double
f :: Double -> Double
f Double
x =
  if Double
x forall a. Ord a => a -> a -> Bool
<= Double
0
    then Double
0
    else Double
x

-- | @E(r) = { r, r ≤ 1; 1/r², r > 1}@
e :: Double -> Double
e :: Double -> Double
e Double
r =
  if Double
r forall a. Ord a => a -> a -> Bool
<= Double
1
    then Double
r
    else Double
1 forall a. Fractional a => a -> a -> a
/ Double
r forall a. Floating a => a -> a -> a
** Double
2

-- * Exercise 3.3

-- | Returns 'True' if the input character is @\'X\'@ or @\'Y\'@
-- or else 'False'.
--
-- >>> isXorY 'X'
-- True
-- >>> isXorY 'Y'
-- True
-- >>> isXorY 'Z'
-- False
isXorY :: Char -> Bool
isXorY :: Char -> Bool
isXorY Char
'X' = Bool
True
isXorY Char
'Y' = Bool
True
isXorY Char
_ = Bool
False

------------------
-- * Exercise 3.4
------------------

-- | Returns @100@ if the person is checking bags and @0@ if not.
-- Implemented with @if-then-else@.
bagFee :: Bool -> Int
bagFee :: Bool -> Int
bagFee Bool
isCheckingBags = if Bool
isCheckingBags then Int
100 else Int
0

-- | Returns @100@ if the person is checking bags and @0@ if not.
-- Implemented with pattern matching on the input.
bagFee2 :: Bool -> Int
bagFee2 :: Bool -> Int
bagFee2 Bool
True = Int
100
bagFee2 Bool
_ = Int
0

------------------
-- * Exercise 3.5
------------------

-- | Returns 'True' if the given integer is greater than 50 or else 'False'
greaterThan50 :: Integer -> Bool
greaterThan50 :: Integer -> Bool
greaterThan50 Integer
n = Integer
n forall a. Ord a => a -> a -> Bool
> Integer
50

------------------
-- * Exercise 3.6
------------------

-- | Double the score without going over 100
amazingCurve :: Int -> Int
amazingCurve :: Int -> Int
amazingCurve Int
score = forall a. Ord a => a -> a -> a
min Int
100 (Int
score forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)

------------------
-- * Exercise 3.7
------------------
{- $ex37
>>> :type bagFee False
bagFee False :: Int

>>> bagFee False
0
-}

------------------
-- * Exercise 3.8
------------------

-- | @circleRadius = 3.5@
circleRadius :: Double
circleRadius :: Double
circleRadius = Double
3.5

-- | @cot x = 1 / tan x@
cot :: Double -> Double
cot :: Double -> Double
cot Double
x = Double
1 forall a. Fractional a => a -> a -> a
/ forall a. Floating a => a -> a
tan Double
x

-- | @fe epsilon = epsilon * tan (epsilon * pi / 2)@
fe :: Double -> Double
fe :: Double -> Double
fe Double
epsilon = Double
epsilon forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
tan (Double
epsilon forall a. Num a => a -> a -> a
* forall a. Floating a => a
pi forall a. Fractional a => a -> a -> a
/ Double
2)

-- | @fo epsilon = -epsilon * cot (epsilon * pi / 2)@
fo :: Double -> Double
fo :: Double -> Double
fo Double
epsilon = -Double
epsilon forall a. Num a => a -> a -> a
* Double -> Double
cot (Double
epsilon forall a. Num a => a -> a -> a
* forall a. Floating a => a
pi forall a. Fractional a => a -> a -> a
/ Double
2)

-- | @g nu epsilon = sqrt (nu ** 2 - epsilon ** 2)@
g :: Double -> Double -> Double
g :: Double -> Double -> Double
g Double
nu Double
epsilon = forall a. Floating a => a -> a
sqrt (Double
nu forall a. Floating a => a -> a -> a
** Double
2 forall a. Num a => a -> a -> a
- Double
epsilon forall a. Floating a => a -> a -> a
** Double
2)

------------------
-- * Exercise 3.9
------------------
{- $ex39
__How many functions with type @Bool -> Bool@ are there?__

/There are 4 @Bool -> Bool@ functions./

__What would be good names for them?__

/@alwaysFalse@, @alwaysTrue@, 'identity', and 'not'/

__How many functions have type @Bool -> Bool -> Bool@?__

/There are 16 @Bool -> Bool -> Bool@ functions./

Source: [The 16 Boolean Logic Functions of Two-Input Systems](https://www.allaboutcircuits.com/technical-articles/16-boolean-logic-functions-of-2-input-system/)
-}

------------------
-- * Exercise 3.10
------------------
-- $ex310
-- > True || False && False