------------------------------------------------------------------------------
--
	 Haskell : The Craft of Functional Programming , 3e
	  
	 ( c ) Addison - Wesley , 1996 - 2011 .
--
	 Chapter 3
--
------------------------------------------------------------------------------

module Chapter3 where

import Prelude hiding (max)
import Test.QuickCheck 

  The import statement which follows hides certain of the Prelude functions
-- so that they can be given the definitions they have in their book.


  The Booleans .
-- ^^^^^^^^^^^^^

-- Exclusive or: this gives the result True if one of its arguments is True and
-- the other False, and gives the result False in other cases.

exOr :: Bool -> Bool -> Bool
exOr x y = (x || y) && not (x && y)

-- Using literals instead of variables in a definition; a simple example of
-- pattern matching to give another definition of `not', ...

myNot :: Bool -> Bool
myNot True  = False
myNot False = True

prop_myNot :: Bool -> Bool

prop_myNot x =
    not x == myNot x

-- ... and of `exclusive or'.

exOr1 True  x = not x
exOr1 False x = x

  Test exOrs

prop_exOrs :: Bool -> Bool -> Bool

prop_exOrs x y =
    exOr x y == exOr1 x y

prop_exOr2 :: Bool -> Bool -> Bool

prop_exOr2 x y =
    exOr x y == (x /= y)

-- Integers and guards.
-- ^^^^^^^^^^^^^^^^^^^^

  A to test whether three Ints are equal .

threeEqual :: Integer -> Integer -> Integer -> Bool
threeEqual m n p = (m==n) && (n==p)

  The maximum of two integers ; this is already defined in the Prelude ,
-- so its definition is hidden by the import statement at the top of this file.

max :: Integer -> Integer -> Integer
max x y
  | x >= y      = x
  | otherwise   = y

  The maximum of three integers .

maxThree :: Integer -> Integer -> Integer -> Integer
maxThree x y z
  | (x >= y) && (x >= z)    = x
  | y >= z                  = y
  | otherwise               = z

  An alternative definition of  which uses if ... then ... else ...

max' :: Integer -> Integer -> Integer
max' x y
  = if x >= y then x else y

prop_compareMax :: Integer -> Integer -> Bool
prop_compareMax x y =
    max x y == max' x y

prop_max1, prop_max2, prop_max3 :: Integer -> Integer -> Bool

prop_max1 x y =
    x <= max x y && y <= max x y

prop_max2 x y =
    x == max x y || y == max x y

prop_max3 x y =
    (x == max x y) `exOr` (y == max x y)


-- Characters.
  ^^^^^^^^^^^

-- Converting lower-case letters to upper-case; does something odd if you apply
-- it to anythig else: how would you modify it to return anything else
-- unchanged?
 
toUpper :: Char -> Char
toUpper ch = toEnum (fromEnum ch + offset)

offset = fromEnum 'A' - fromEnum 'a'

-- A check whether a character is a digit.

isDigit :: Char -> Bool
isDigit ch = ('0' <= ch) && (ch <= '9')


-- The String type
  ^^^^^^^^^^^^^^^

-- Example strings

str1, str2, str3, str4, str5 :: String

str1 = "baboon"
str2 = ""
str3 = "\99a\116"
str4 = "gorilla\nhippo\nibex"
str5 = "1\t23\t456"

pstr1, pstr2, pstr3, pstr4, pstr5 :: IO ()

pstr1 = putStr str1
pstr2 = putStr str2
pstr3 = putStr str3
pstr4 = putStr str4
pstr5 = putStr str5



-- Some syntax.
  ^^^^^^^^^^^^

  Layout : two definitions on one line , separated by a ` ; ' .

answer = 42 ;   facSix = 720 

  Adding two integers : you can use longer names for variables than x and y !

addTwo :: Integer -> Integer -> Integer
addTwo first second = first+second

  Defining an operator for yourself : another version of  !

(&&&) :: Integer -> Integer -> Integer
x &&& y 
  | x > y       = y
  | otherwise   = x

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



----------------------------------------------------------------------------
 so that they can be given the definitions they have in their book.
 ^^^^^^^^^^^^^
 Exclusive or: this gives the result True if one of its arguments is True and
 the other False, and gives the result False in other cases.
 Using literals instead of variables in a definition; a simple example of
 pattern matching to give another definition of `not', ...
 ... and of `exclusive or'.
 Integers and guards.
 ^^^^^^^^^^^^^^^^^^^^
 so its definition is hidden by the import statement at the top of this file.
 Characters.
 Converting lower-case letters to upper-case; does something odd if you apply
 it to anythig else: how would you modify it to return anything else
 unchanged?
 A check whether a character is a digit.
 The String type
 Example strings
 Some syntax.
	 Haskell : The Craft of Functional Programming , 3e
	  
	 ( c ) Addison - Wesley , 1996 - 2011 .
	 Chapter 3

module Chapter3 where

import Prelude hiding (max)
import Test.QuickCheck 

  The import statement which follows hides certain of the Prelude functions


  The Booleans .


exOr :: Bool -> Bool -> Bool
exOr x y = (x || y) && not (x && y)


myNot :: Bool -> Bool
myNot True  = False
myNot False = True

prop_myNot :: Bool -> Bool

prop_myNot x =
    not x == myNot x


exOr1 True  x = not x
exOr1 False x = x

  Test exOrs

prop_exOrs :: Bool -> Bool -> Bool

prop_exOrs x y =
    exOr x y == exOr1 x y

prop_exOr2 :: Bool -> Bool -> Bool

prop_exOr2 x y =
    exOr x y == (x /= y)


  A to test whether three Ints are equal .

threeEqual :: Integer -> Integer -> Integer -> Bool
threeEqual m n p = (m==n) && (n==p)

  The maximum of two integers ; this is already defined in the Prelude ,

max :: Integer -> Integer -> Integer
max x y
  | x >= y      = x
  | otherwise   = y

  The maximum of three integers .

maxThree :: Integer -> Integer -> Integer -> Integer
maxThree x y z
  | (x >= y) && (x >= z)    = x
  | y >= z                  = y
  | otherwise               = z

  An alternative definition of  which uses if ... then ... else ...

max' :: Integer -> Integer -> Integer
max' x y
  = if x >= y then x else y

prop_compareMax :: Integer -> Integer -> Bool
prop_compareMax x y =
    max x y == max' x y

prop_max1, prop_max2, prop_max3 :: Integer -> Integer -> Bool

prop_max1 x y =
    x <= max x y && y <= max x y

prop_max2 x y =
    x == max x y || y == max x y

prop_max3 x y =
    (x == max x y) `exOr` (y == max x y)


  ^^^^^^^^^^^

 
toUpper :: Char -> Char
toUpper ch = toEnum (fromEnum ch + offset)

offset = fromEnum 'A' - fromEnum 'a'


isDigit :: Char -> Bool
isDigit ch = ('0' <= ch) && (ch <= '9')


  ^^^^^^^^^^^^^^^


str1, str2, str3, str4, str5 :: String

str1 = "baboon"
str2 = ""
str3 = "\99a\116"
str4 = "gorilla\nhippo\nibex"
str5 = "1\t23\t456"

pstr1, pstr2, pstr3, pstr4, pstr5 :: IO ()

pstr1 = putStr str1
pstr2 = putStr str2
pstr3 = putStr str3
pstr4 = putStr str4
pstr5 = putStr str5



  ^^^^^^^^^^^^

  Layout : two definitions on one line , separated by a ` ; ' .

answer = 42 ;   facSix = 720 

  Adding two integers : you can use longer names for variables than x and y !

addTwo :: Integer -> Integer -> Integer
addTwo first second = first+second

  Defining an operator for yourself : another version of  !

(&&&) :: Integer -> Integer -> Integer
x &&& y 
  | x > y       = y
  | otherwise   = x
