Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nabilhassein/def801a9f41a5942135827a677afc7e4 to your computer and use it in GitHub Desktop.
Save nabilhassein/def801a9f41a5942135827a677afc7e4 to your computer and use it in GitHub Desktop.
-- long brute force solution to exercise 7 on p. 20 of "Conceptual Mathematics"
-- if you don't have haskell on your computer, paste all this into:
-- https://replit.com/languages/haskell
-- this is how we define a data type in Haskell. think of it as a set
data Bit = Zero | One deriving (Show, Eq)
-- the last part tells Haskell to figure out how to print Bits, and that
-- Zero equals Zero, One equals One, and Zero is different from One
-- this is a type declaration. think domain and codomain
identity :: Bit -> Bit
-- this is a function definition. the output is always the same as the input
identity bit = bit -- bit is a variable. we could have called it "x"
-- note the case sensitivity: upper case = types, lower case = something else
zero :: Bit -> Bit
zero _ = Zero -- this is a function that always gives the same output
-- so we don't bother to give a name to the unused variable
one :: Bit -> Bit
one _ = One
-- this function uses "pattern matching" -- like a piecewise function in math
bitflip :: Bit -> Bit
bitflip Zero = One
bitflip One = Zero
all_functions :: [Bit -> Bit]
all_functions = [identity, zero, one, bitflip]
idempotent_functions :: [Bit -> Bit]
idempotent_functions = filter is_idempotent all_functions
where
is_idempotent :: (Bit -> Bit) -> Bool
is_idempotent f = f (f Zero) == f Zero && f (f One) == f One
main = print (length idempotent_functions)
-- you can do the same thing for a type "Ternary" you define to solve exercise 6
-- hard part: hand-writing all 27 possible functions of type Ternary -> Ternary
-- i was inspired here by an old abstract algebra homework i got in college
-- solution: https://github.com/nabilhassein/exercises/blob/master/Algebra.lhs
-- but a better solution than this brute-force method is the formula here:
-- https://en.wikipedia.org/wiki/Idempotence#Idempotent_functions
-- boring definitions. i'm sure there's a better generic way to do this
-- but 17 isn't too many to brute force ;)
data A = John | Mary | Sam deriving (Show, Eq)
data B = Eggs | Coffee deriving (Show, Eq)
a_to_b_1, a_to_b_2, a_to_b_3, a_to_b_4, a_to_b_5, a_to_b_6, a_to_b_7, a_to_b_8 :: A -> B
b_to_a_1, b_to_a_2, b_to_a_3, b_to_a_4, b_to_a_5, b_to_a_6, b_to_a_7, b_to_a_8, b_to_a_9 :: B -> A
a_to_b_1 John = Eggs
a_to_b_1 Mary = Eggs
a_to_b_1 Sam = Eggs
a_to_b_2 John = Eggs
a_to_b_2 Mary = Eggs
a_to_b_2 Sam = Coffee
a_to_b_3 John = Eggs
a_to_b_3 Mary = Coffee
a_to_b_3 Sam = Eggs
a_to_b_4 John = Eggs
a_to_b_4 Mary = Coffee
a_to_b_4 Sam = Coffee
a_to_b_5 John = Coffee
a_to_b_5 Mary = Eggs
a_to_b_5 Sam = Eggs
a_to_b_6 John = Coffee
a_to_b_6 Mary = Coffee
a_to_b_6 Sam = Eggs
a_to_b_7 John = Coffee
a_to_b_7 Mary = Eggs
a_to_b_7 Sam = Coffee
a_to_b_8 John = Coffee
a_to_b_8 Mary = Coffee
a_to_b_8 Sam = Coffee
b_to_a_1 Eggs = John
b_to_a_1 Coffee = John
b_to_a_2 Eggs = John
b_to_a_2 Coffee = Mary
b_to_a_3 Eggs = John
b_to_a_3 Coffee = Sam
b_to_a_4 Eggs = Mary
b_to_a_4 Coffee = Mary
b_to_a_5 Eggs = Mary
b_to_a_5 Coffee = John
b_to_a_6 Eggs = Mary
b_to_a_6 Coffee = Sam
b_to_a_7 Eggs = Sam
b_to_a_7 Coffee = Sam
b_to_a_8 Eggs = Sam
b_to_a_8 Coffee = John
b_to_a_9 Eggs = Sam
b_to_a_9 Coffee = Mary
a_to_b_fns :: [A -> B]
a_to_b_fns = [a_to_b_1, a_to_b_2, a_to_b_3, a_to_b_4, a_to_b_5, a_to_b_6, a_to_b_7, a_to_b_8]
b_to_a_fns :: [B -> A]
b_to_a_fns = [b_to_a_1, b_to_a_2, b_to_a_3, b_to_a_4, b_to_a_5, b_to_a_6, b_to_a_7, b_to_a_8, b_to_a_9]
-- actual logic
a_to_b_to_a_id_pairs :: [A -> A]
a_to_b_to_a_id_pairs = filter is_identity [g . f | g <- b_to_a_fns, f <- a_to_b_fns]
where
is_identity :: (A -> A) -> Bool
is_identity func = func John == John && func Mary == Mary && func Sam == Sam
b_to_a_to_b_id_pairs :: [B -> B]
b_to_a_to_b_id_pairs = filter is_identity [k . h | h <- b_to_a_fns, k <- a_to_b_fns]
where
is_identity :: (B -> B) -> Bool
is_identity func = func Eggs == Eggs && func Coffee == Coffee
main = do
putStrLn "Answer to exercise 8"
print (length a_to_b_to_a_id_pairs)
putStrLn "Answer to exercise 9"
print (length b_to_a_to_b_id_pairs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment