Skip to content

Instantly share code, notes, and snippets.

@techtangents
Last active March 9, 2020 01:02
Show Gist options
  • Save techtangents/4089e563352b4678944c to your computer and use it in GitHub Desktop.
Save techtangents/4089e563352b4678944c to your computer and use it in GitHub Desktop.
join bimap explanation
-- Consider the function type constructor "->" in infix form:
-- e.g. "a -> b" is the same as "(->) a b"
-- Partially applied, "(->) a" is the "reader" type,
-- i.e. functions that "read" an 'a'. "(->) a" is a Monad - the Reader Monad.
-- Consider the join function:
join :: Monad m => m (m a) -> m a
-- replace a with b:
join :: Monad m => m (m b) -> m b
-- Add some parens:
join :: Monad m => (m (m b)) -> (m b)
-- Now specialise to Reader Monad: just textually replace m with ((->) a)
join :: (((->) a) (((->) a) b)) -> (((->) a) b)
-- (->) is right-associative, so we can drop some parens:
join :: ((->) a ((->) a b)) -> ((->) a b)
-- Then change to infix:
join :: (a -> a -> b) -> a -> b
-- Now, you passed "bimap" to join. bimap is:
bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
-- and we're passing this as the (a -> a -> b) argument.
bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
-- ( a ) -> ( a ) -> ( b )
-- To fit this type signature, bimap specialises to:
bimap :: Bifunctor p => (a -> b) -> (a -> b) -> p a a -> p b b
-- We're using this on "uncurry (/)", so our bifunctor is pair, so bimap specialises further to:
bimap :: (a -> b) -> (a -> b) -> (a,a) -> (b,b)
-- So, "join bimap", specialised to pairs is:
join bimap :: (a -> b) -> (a,a) -> (b,b)
-- A pair (a,a) is a vector of length 2, so "join bimap" is the fmap for this type!
-- Pair already has a Functor, so let's newtype it to demonstrate the vector's Functor:
newtype Vec2 a = Vec2 (a,a) deriving Show
instance Functor Vec2 where
fmap f (Vec2 p) = Vec2 $ join bimap f p
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment