Skip to content

Instantly share code, notes, and snippets.

@Icelandjack
Last active March 31, 2025 00:09
Show Gist options
  • Save Icelandjack/2fb0b18c06a023d93d4f5d61b7f8a8cc to your computer and use it in GitHub Desktop.
Save Icelandjack/2fb0b18c06a023d93d4f5d61b7f8a8cc to your computer and use it in GitHub Desktop.
_jack Glossary

A function mapped on each side.

Any function (profunctor/category) has "inputs" and "outputs". First argument: input (contravariant), second argument: output (covariant). covariant argument.

πŸŸ₯🟦 :: πŸŸ₯ -> 🟦
🟦🟩 :: 🟦 -> 🟩

When composing, it works like domino pieces: πŸ€Ί >>> πŸ‚ = πŸ€» the connecting parts must be match but prefer using colours for it.

πŸŸ₯🟦 >>> 🟦🟩 :: πŸŸ₯ -> 🟩

The middle type has disappeared from the input/output interface of the function. 🟦, as far as composition goes, is an existential type which is not reflected in the output.

(>>>) :: cat πŸŸ₯ 🟦 -> cat 🟦 🟩 -> cat πŸŸ₯ 🟩 

If we want to modify the input and output of πŸŸ₯🟦 :: πŸŸ₯ -> 🟦, a natural pattern emerges: They are mapped at a different variance. What can compose on the left πŸŸ₯? Anything that outputs πŸŸ₯.

πŸŸ₯'πŸŸ₯ :: πŸŸ₯' -> πŸŸ₯
     :: πŸŸ₯ <- πŸŸ₯'

And what about the right 🟦? Anything that takes in 🟦.

🟦🟦' :: 🟦 -> 🟦'

This natural observation demonstrates through child-like toys how contravariance emerges from the nature of composition.

πŸŸ₯'πŸŸ₯ >>> πŸŸ₯🟦 >>> 🟦🟦' :: πŸŸ₯' -> 🟦'

Here is how this observation is interprated as annotated functors.

        ,------------------- Op Hask :: Cat Type
        |       ,----------- Hask    :: Cat Type
        |       |       ,--- Hask    :: Cat Type
        |       |       |
(->) :: Type -> Type -> Type

with the mapping function

dimap :: (Ρ–n <- Ρ–n') -> (out -> out') -> ((Ρ–n -> out) -> (Ρ–n' -> out'))
dimap pre post f = pre >>> f >>> post
dimap :: (πŸŸ₯ <- πŸŸ₯') -> (🟦 -> 🟦') -> ((πŸŸ₯ -> 🟦) -> (πŸŸ₯' -> 🟦'))
dimap πŸŸ₯'πŸŸ₯ 🟦🟦' πŸŸ₯🟦 = πŸŸ₯'πŸŸ₯ >>> πŸŸ₯🟦 >>> 🟦🟦'

And here is how it is interpreted for an arbitrary category cat :: Cat k:

       ,------------- Op cat :: Cat k
       |    ,-------- cat    :: Cat k
       |    |    ,--- Hask   :: Cat Type
       |    |    |
cat :: k -> k -> Type
dimap :: Category cat => Op cat Ρ–n Ρ–n' -> cat out out' -> (cat Ρ–n out -> cat Ρ–n' out')
dimap (Op pre) post f = pre >>> f >>> post

Every category gives rise to a Profunctor { Input = cat, Output = cat } using record syntax for associated types.

  Profunctor { Input = cat, Output = cat }
=  Bifunctor { Source1 = Op cat, Source2 = cat, Target = Hask }
=    Functor { Source = Op cat, Target = Nat cat Hask }
dimap :: Profunctor { Input = input, Output = output } pro
      -> Op input Ρ–n Ρ–n'
      -> output out out'
      -> (pro Ρ–n out -> pro Ρ–n' out')

Annotated functors

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