Saturday, 12 October 2013

Haskell Lens Isomorphisms

A small snippet of code I wrote to try and get my head around Van Laarhoven lenses. It shows the isomorphisms between three common representations of lenses.

{-# LANGUAGE RankNTypes #-}

-- Traditional lens as a pair of getter and setter
type Lens a b = (b -> a, b -> a -> b)

-- Lens implemented with a store comonad
data Store a b = Store { get :: a, set :: a -> b }

instance Functor (Store a) where
    fmap f (Store a ab) = Store a (f . ab)

type SLens a b = b -> Store a b

-- Van Laarhoven lens
type VLLens a b = forall g . Functor g => (a -> g a) -> (b -> g b)

-- Lens / SLens isomorphism

lensToSlens :: Lens a b -> SLens a b
lensToSlens (getter, setter) = \b -> Store (getter b) (setter b)

sLensToLens :: SLens a b -> Lens a b
sLensToLens slens = (get . slens, set . slens)

-- SLens / VLLens isomorphism

sLensToVLLens :: SLens a b -> VLLens a b
sLensToVLLens slens = \f b -> let Store a ab = slens b in fmap ab $ f a

vLLensToSLens :: VLLens a b -> SLens a b
vLLensToSLens vllens = \b -> ((flip vllens) b) (\a -> Store a id)

No comments: