Skip to content

Instantly share code, notes, and snippets.

@denisshevchenko
Created March 28, 2019 09:46
Show Gist options
  • Save denisshevchenko/6ca8b731b257f6c36b08bd23dccd984d to your computer and use it in GitHub Desktop.
Save denisshevchenko/6ca8b731b257f6c36b08bd23dccd984d to your computer and use it in GitHub Desktop.
title author
Contravariant and Trace
Denis Shevchenko

Functor

f a

What is it?


Functor

Maybe Int

Functor

Maybe Int is a producer.


Functor

Maybe Int is a producer: mapping produces some Int value in Maybe context.


Functor

> fmap (* 10) $ Just 3
Just 30

Contravariant Functor

contramap :: (a -> b) -> f b -> f a

Contravariant Functor

contramap :: (a -> b) -> f b -> f a
fmap      :: (a -> b) -> f a -> f b

Contravariant Functor

fmap :: (a -> b) -> f a -> f b

We can apply a -> b to f a to produce f b.


Contravariant Functor

contramap :: (a -> b) -> f b -> f a

But we cannot apply a -> b to f b to produce f a. :-(


Contravariant Functor

contramap :: (a -> b) -> f b -> f a

But we cannot apply a -> b to f b to produce f a. :-(

This is because f b is not a producer!


Contravariant Functor

newtype MyStringifier a = MyStringifier { runStringifier :: a -> String }

Contravariant Functor

intStringifier :: MyStringifier Int
intStringifier =  MyStringifier show

Contravariant Functor

What is MyStringifier Int?


Contravariant Functor

MyStringifier Int is a consumer!


Contravariant Functor

MyStringifier Int is a consumer: it consumes Int value and stringifies it.


Contravariant Functor

instance Contravariant MyStringifier where
    contramap f (MyStringifier stringifier) = MyStringifier (stringifier . f)

Contravariant Functor

                                                             
                                                             stringifier . f

Contravariant Functor

newtype MySuperNumber = MySuperNumber Int

Contravariant Functor

newtype MySuperNumber = MySuperNumber Int

someFunc :: MySuperNumber -> Int
someFunc (MySuperNumber i) = i * 10

Contravariant Functor

newtype MySuperNumber = MySuperNumber Int

someFunc :: MySuperNumber -> Int
someFunc (MySuperNumber i) = i * 10

intStringifier :: MyStringifier Int
intStringifier =  MyStringifier show

Contravariant Functor

newtype MySuperNumber = MySuperNumber Int

someFunc :: MySuperNumber -> Int
someFunc (MySuperNumber i) = i * 10

intStringifier :: MyStringifier Int
intStringifier =  MyStringifier show

main :: IO ()
main = do
    let superNumberStringifier = contramap someFunc intStringifier
        result = runStringifier superNumberStringifier $ MySuperNumber 12
    putStrLn result

Contravariant Functor











                                 contramap someFunc intStringifier



Contravariant Functor

instance Contravariant MyStringifier where
    contramap f (MyStringifier stringifier) = MyStringifier (stringifier . f)

Contravariant Functor

    
    contramap someFunc intStringifier = MyStringifier (runStringifier intStringifier . someFunc)

Contravariant Functor

    
    contramap someFunc intStringifier = MyStringifier (runStringifier intStringifier . someFunc)
                                                       -----------------------------
                                                       Int -> String                   

Contravariant Functor

    
    contramap someFunc intStringifier = MyStringifier (runStringifier intStringifier . someFunc)
                                                       -----------------------------   --------
                                                       Int -> String                   MySuperNumber -> Int

Contravariant Functor

    
    contramap someFunc intStringifier = MyStringifier (runStringifier intStringifier . someFunc)
                                                       ----------------------------------------
                                                       MySuperNumber -> String

Contravariant Functor

someFunc :: MySuperNumber -> Int
someFunc (MySuperNumber i) = i * 10

main :: IO ()
main = do
    let superNumberStringifier = contramap someFunc intStringifier
        result = runStringifier superNumberStringifier $ MySuperNumber 12
    putStrLn result

Contravariant Functor

intStringifier :: MyStringifier Int

Contravariant Functor

intStringifier         :: MyStringifier Int
superNumberStringifier :: MyStringifier MySuperNumber

Contravariant Functor

import           Data.Functor.Contravariant

newtype Trace m message = Trace { tracing :: message -> m () }

instance Contravariant (Trace m) where
    contramap f tracer = Trace (tracing tracer . f)

newtype MySuperNumber = MySuperNumber Int

main :: IO ()
main = do
    let intTracer :: Trace IO Int
        intTracer =  Trace print

        someFunc :: MySuperNumber -> Int
        someFunc (MySuperNumber i) = i * 10

        superNumberTracer :: Trace IO MySuperNumber
        superNumberTracer = contramap someFunc intTracer

        actualTracer = tracing superNumberTracer
    actualTracer $ MySuperNumber 12

Contravariant Functor

someFunc didn't change, even if we use Trace with IO!


Contravariant Functor

main :: IO ()
main = do
    c <- defaultConfigStdout
    tr :: Trace IO String <- setupTrace (Right c) "simple"
    logDebug tr "this is a debug message"

Contravariant Functor

[iohk.simple:Debug:ThreadId 4] [2019-03-27 21:37:24.66 UTC] "this is a debug message"

Contravariant Functor

data D = D { ss :: String, ii :: Int }
    deriving (Generic, Show, Eq, Ord, FromJSON, ToJSON)

main :: IO ()
main = do
    c <- defaultConfigStdout
    tr :: Trace IO D <- setupTrace (Right c) "simple"
    logDebug tr (D "this is a crazy debug message" 12)

Contravariant Functor

[iohk.simple:Debug:ThreadId 4] [2019-03-27 21:37:24.66 UTC] D {ss = "this is a crazy debug message", ii = 12}

Contravariant Functor

The end (for now...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment