import Data.Bits import Data.Char import Data.Functor.Contravariant data Result i o = Result { input :: i, actual :: o, expected :: o, result :: Bool } deriving (Show, Eq, Ord) -------------------- -- Exercise 1 -------------------- newtype Boxed a = Boxed {unbox :: a} instance Functor Boxed where fmap f (Boxed a) = Boxed (f a) test11 = Result x actual expected (actual == expected) where x = 1 actual = unbox (fmap id b) expected = unbox b b = Boxed { unbox = x :: Integer } -- >>> test11 -- Result {input = 1, actual = 1, expected = 1, result = True} -- test12 = Result x actual expected (actual == expected) where x = 1 actual = unbox (fmap (f . g) b) expected = unbox (fmap f $ fmap g b) b = Boxed { unbox = x :: Integer } f = (+9) g = (*11) -- >>> test12 -- Result {input = 1, actual = 20, expected = 20, result = True} -- -------------------- -- Exercise 2 -------------------- newtype FromInt b = FromInt {fun :: Int -> b} instance Functor FromInt where fmap f (FromInt b) = FromInt (\ x -> f (b x)) test21 = Result x actual expected (actual == expected) where x = 2 actual = ((fun (fmap id converter)) x) expected = (fun (converter) x) converter = FromInt {fun = \ val -> val * (-1)} -- >>> test21 -- Result {input = 2, actual = -2, expected = -2, result = True} -- test22 = Result x actual expected (actual == expected) where x = 7 actual = (fun (fmap g $ fmap f converter)) x expected = (fun ((g . f) <$> converter)) x converter = FromInt {fun = \ val -> chr ((ord 'A') + val)} f = \ char -> char:"B" g = \ str -> str ++ "C" -- >>> test22 -- Result {input = 7, actual = "HBC", expected = "HBC", result = True} -- -------------------- -- Exercise 3 -------------------- newtype ToInt b = ToInt {conv :: b -> Int} instance Contravariant ToInt where contramap f (ToInt g) = ToInt (\ value -> g (f value)) strHash :: String -> Int strHash value = realHash 0 value where realHash acc "" = acc realHash acc (char:str) = realHash (acc + ((ord char) .&. 0b11010110)) str test3 = [ (Result myStr strExpected strActual (strExpected == strActual)), (Result [myChar] expected actual (expected == actual)) ] where -- Create object `toInt` for converting strings to an Int hash (using the "strHash" function) toInt = ToInt strHash -- Converting a string to an Int hash using `toInt` should yield -- the same result like using `strHash` directly strActual = conv toInt myStr strExpected = strHash myStr -- Create a function for converting a `Char` to a `String` charToStr = \x -> [x] -- Wrap `toInt` in a (Char -> String) converter using `contramap` -- effectively using `toInt` as a `Char -> Int` function actual = conv (contramap charToStr toInt) myChar -- should yield the same result like using `charToStr` and the original `toInt` directly expected = conv toInt (charToStr myChar) -- Value for testing the `toInt` implementation myStr = "Hello World" -- Value for testing the `toInt` implementation -- wrapped in the `charToStr` function myChar = 'V' -- Showing the result of the `String` and the `Char` test -- >>> mapM_ putStrLn (map show test3) -- Result {input = "Hello World", actual = 712, expected = 712, result = True} -- Result {input = "V", actual = 86, expected = 86, result = True} --