Introduction to Yoneda and Coyoneda
url: “https://gist.github.com/gregberns/ede18190d5117eea6fb51815e2eab9b2"
#source/article
The Yoneda lemma can speed up fmap
with long lists or deep trees.
-- Defining the type
newtype Yoneda f a = Yoneda {
runYoneda :: forall x. (a -> x) -> F x
}
instance Functor (Yoneda f) where
-- fmap :: (a -> b) -> (Yoneda f a -> Yoneda f b)
fmap f y = Yoneda $ \b2x -> runYoneda y (b2x . f)
We get a function wrapped in Yoneda
— delayed execution.
Fusing functions to run with b2x . f
— we build computation and run everything, on a list for example, in a single pass.
From Yoneda one-to-one relationship, we get two functions
toYoneda :: f a -> Yoneda f a
toYoneda fa = Yoneda (\ax -> fmap ax fa)
fromYoneda :: Yoneda f a -> f a
fromYoneda y = runYoneda y id
Using Yoneda
:
createYo :: Yoneda Maybe Int
createYo = toYoneda $ Just 42
foo :: Maybe Int
foo = fromYoneda $ fmap (*2) $ fmap (+1) createYo
-- Yoneda fuses these two fmaps.
Yoneda can fuse if lists or trees are large.