-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- |
-- 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 Double -> Double -> Bool
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 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
1
    then Double
r
    else Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
r Double -> Double -> Double
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 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
50

------------------

-- * Exercise 3.6

------------------

-- | Double the score without going over 100
--
-- >>> amazingCurve 30
-- 60
-- >>> amazingCurve 80
-- 100
amazingCurve :: Int -> Int
amazingCurve :: Int -> Int
amazingCurve Int
score = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
100 (Int
score Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
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 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
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 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
tan (Double
epsilon Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
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 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
cot (Double
epsilon Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
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 = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
nu Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
epsilon Double -> Double -> Double
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