Skip to content

Instantly share code, notes, and snippets.

@Unisay
Created January 28, 2018 19:34
Show Gist options
  • Save Unisay/b4afc5f7a3f753426099565d13906b56 to your computer and use it in GitHub Desktop.
Save Unisay/b4afc5f7a3f753426099565d13906b56 to your computer and use it in GitHub Desktop.
Lens
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
{- https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-and-manipulation -}
module Lens.My where
import Prelude
import Data.Functor.Identity
import Data.Functor.Const
import Lens.Data
type Lens' s a = ∀ f . Functor f => (a -> f a) -> s -> f s
data LensR s a = LensR { viewR :: s -> a
, setR :: a -> s -> s
}
lensRtoLens :: LensR s a -> Lens' s a
lensRtoLens ln f s = flip (setR ln) s <$> f (viewR ln s)
lensToLensR :: ∀ s a . Lens' s a -> LensR s a
lensToLensR ln = LensR (view ln) (set ln)
view :: Lens' s a -> s -> a
view ln = getConst . ln Const
set :: Lens' s a -> a -> s -> s
set ln a = runIdentity . ln (Identity . const a)
over :: Lens' s a -> (a -> a) -> s -> s
over ln f = runIdentity . ln (Identity . f)
lname :: Lens' Person Name
lname f (Person n ag ad) = fmap (\n' -> Person n' ag ad) (f n)
laddress :: Lens' Person Address
laddress f (Person n ag ad) = Person n ag <$> f ad
lstreet :: Lens' Address Street
lstreet f (Address s h) = flip Address h <$> f s
lpersonStreet :: Lens' Person Street
lpersonStreet = laddress . lstreet
type Traversal s a = ∀ f . Applicative f => (a -> f a) -> s -> f s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment