van Laarhoven lens
fp category haskell
2021-10-18
2021-11-11
basic Lensと
type Lens s a = forall f. Functor f => (a -> f a) -> (s -> f s)
の対応を見る
{-# LANGUAGE Rank2Types #-}
import Control.Applicative
import Control.Monad.Identity
type Lens s a = forall f. Functor f => (a -> f a) -> (s -> f s)
get :: Lens s a -> s -> a
get l = getConst . l Const
update :: Lens s a -> (a -> a) -> s -> s
update l m = runIdentity . l (Identity . m)
set :: Lens s a -> a -> s -> s
set l b a = update l (const b) a
compose :: Lens b c -> Lens a b -> Lens a c
compose r s = s . r
fstL :: Lens (a, b) a
fstL f (x,y) = fmap (\a -> (a,y)) (f x)
sndL :: Lens (a, b) b
sndL x (a,b) = (,) a <$> x b
main = do
print $ get fstL (1, 2)
-- => getConst . (fstL Const) (1, 2)
-- => getConst . (\x (a,b) -> (,b) <$> x a) (1, 2)
-- => getConst . (\(a, b) -> (,b) <$> Const a) (1, 2)
-- => getConst . ((,2) <$> Const 1)
-- => getConst . (Const 1)
-- => 1
print $ update (fstL . sndL) (*2) ((3, 4), 5)
-- like `pair.(fstL.sndL) *= 2`Isomorphism Lens
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ExistentialQuantification #-}
import Data.Bifunctor
-- type Lens s a = exists r. s <-> (a, r)
-- isomorphisms/bijections between type 'a' & 'b'
-- Iso has isomorphism law: fw i . bw i = bw i . fw i = id
data Iso a b = Iso
{ fw :: a -> b
, bw :: b -> a
}
-- unpack the Iso type
data Lens s a = forall r. Lens (Iso s (a,r))
get :: Lens s a -> s -> a
get (Lens l) = fst . fw l
update :: Lens s a -> (a -> a) -> (s -> s)
update (Lens l) f = bw l . first f . fw l
-- TODO: how implement `compose`, `fstL`, `sndL` ?
main = do
print 0
-- print $ get sndL (1, 2)
-- print $ update (fstL `compose` sndL) (*2) ((3, 4), 5)