packages feed

pointless-lenses-0.0.8: src/Generics/Pointless/DLenses/Combinators.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Generics.Pointless.DLenses.Combinators
-- Copyright   :  (c) 2011 University of Minho
-- License     :  BSD3
--
-- Maintainer  :  hpacheco@di.uminho.pt
-- Stability   :  experimental
-- Portability :  non-portable
--
-- Pointless Lenses:
-- bidirectional lenses with point-free programming
-- 
-- This module lifts a standard set of point-free combinators into bidirectional delta-lenses.
--
-----------------------------------------------------------------------------

module Generics.Pointless.DLenses.Combinators where

import Data.Relation
import Data.Shape
import Generics.Pointless.DLenses
import Generics.Pointless.DLenses.ShapeCombinators
import Generics.Pointless.Lenses (Lens)
import qualified Generics.Pointless.Lenses as Lns
import Generics.Pointless.Lenses.Combinators

import Generics.Pointless.Functors
import Generics.Pointless.Combinators

-- | Delta lens composition
infixr 9 .<~
(.<~) :: (Shapely s,Shapely v,Shapely u) => DLens v b u c -> DLens s a v b -> DLens s a u c
f .<~ g = DLens get' getd' put' putd' create' created'
    where get' s = get f (get g s)
          getd' s = getd g s .~ getd f (get g s)
          put' (u,s) dU = put g (put f (u,get g s) dU,s) dV
            where dV = eitherPosR (u,s) (getd f v .~ dU) (locsR v) .~ putd f u v dU
                  v = get g s
          putd' u s dU =  eitherPosR (v',s)
            			    (sumPosR (u,v) (u,s) (locsR u) (getd g s) .~ putd f u v dU)
            			    (inrPosR (u,s))
            		   .~ putd g v' s dV
            where dV = eitherPosR (u,s) (getd f v .~ dU) (locsR v) .~ putd f u v dU
                  (v,v') = (get g s,put f (u,v) dV)
          create' u = create g (create f u)
          created' u = created f u .~ created g (create f u)

-- | Delta lens identity
id_dlns :: Shapely s => DLens s a s a
id_dlns = DLens get' getd' put' putd' create' created'
    where get' s = s
          getd' s = locsR s
          put' (s',s) dS = s'
          putd' s' s dS = inlPosR (s',s)
          create' s' = s'
          created' s' = locsR s'

-- | Delta lens bang
bang_dlns :: Shapely s => (Const One b -> s a) -> DLens s a (Const One) b
bang_dlns f = DLens get' getd' put' putd' create' created'
    where get' s = ConsF _L
          getd' s = emptyR
          put' (v,s) dV = s
          putd' v s dV = inlPosR (v,s)
          create' v = f v
          created' v = emptyR

-- | Delta lens left projection
fst_dlns :: (Shapely f,Shapely g) => (f a -> g a) -> DLens (f :*: g) a f a
fst_dlns h = DLens get' getd' put' putd' create' created'
    where get' (ProdF x y) = x
          getd' (ProdF x y) = inlPosR (x,y)
          put' (x',ProdF x y) dF = ProdF x' y
          putd' x' p@(ProdF x y) dF = sumPosR (x',y) (x',p) (locsR x') (inrPosR (x,y))
          create' x' = ProdF x' (h x')
          created' x' = inv (inlPosR (x',h x'))

-- | Delta lens right projection
snd_dlns :: (Shapely f,Shapely g) => (g a -> f a) -> DLens (f :*: g) a g a
snd_dlns h = DLens get' getd' put' putd' create' created'
    where get' (ProdF x y) = y
          getd' (ProdF x y) = inrPosR (x,y)
          put' (y',ProdF x y) dF = ProdF x y'
          putd' y' p@(ProdF x y) dF = eitherPosR (x,y') (inrPosR (y',p) .~ inlPosR (x,y)) (inlPosR (y',p))
          create' y' = ProdF (h y') y'
          created' y' = inv (inrPosR (h y',y'))

-- | Delta lens product
infix 7 ><<~
(><<~) :: (Shapely f,Shapely g,Shapely h,Shapely i) => DLens f a h b -> DLens g a i b -> DLens (f :*: g) a (h :*: i) b
f ><<~ g = DLens get' getd' put' putd' create' created'
    where get' (ProdF x y) = ProdF (get f x) (get g y)
          getd' (ProdF x y) = sumPosR (get f x,get g y) (x,y) (getd f x) (getd g y)
          put' (ProdF z w,ProdF x y) dV = ProdF (put f (z,x) d1) (put g (w,y) d2)
            where d1 = inv (inlPosR (get f x,get g y)) .~ dV .~ inlPosR (z,w)
                  d2 = inv (inrPosR (get f x,get g y)) .~ dV .~ inrPosR (z,w)
          putd' p1@(ProdF z w) p2@(ProdF x y) dV = eitherPosR (put f (z,x) d1,put g (w,y) d2)
                                               (sumPosR (z,x) (p1,p2) (inlPosR (z,w)) (inlPosR (x,y)) .~ putd f z x d1)
                                               (sumPosR (w,y) (p1,p2) (inrPosR (z,w)) (inrPosR (x,y)) .~ putd g w y d2)
            where d1 = inv (inlPosR (get f x,get g y)) .~ dV .~ inlPosR (z,w)
                  d2 = inv (inrPosR (get f x,get g y)) .~ dV .~ inrPosR (z,w)
          create' (ProdF z w) = ProdF (create f z) (create g w)
          created' (ProdF z w) = sumPosR (create f z,create g w) (z,w) (created f z) (created g w)
	
-- | Delta lens either
infix 4 \/<~
(\/<~) :: (Shapely f,Shapely g,Shapely h) => (h b -> Either One One) -> DLens f a h b -> DLens g a h b -> DLens (f :+: g) a h b
(\/<~) p f g = DLens get' getd' put' putd' create' created'
    where get' (InlF x) = get f x
          get' (InrF y) = get g y
          getd' (InlF x) = getd f x
          getd' (InrF y) = getd g y
          put' (z,InlF x) dV = InlF (put f (z,x) dV)
          put' (z,InrF y) dV = InrF (put g (z,y) dV)
          putd' z (InlF x) dV = putd f z x dV
          putd' z (InrF y) dV = putd g z y dV
          create' z = case (p z) of { Left _  -> InlF (create f z) ; Right _ -> InrF (create g z) }
          created' z = case (p z) of { Left _  -> created f z ; Right _ -> created g z }

-- | Delta lens sum
infix 5 -|-<~
(-|-<~) :: (Shapely f,Shapely g,Shapely h,Shapely i) => DLens f a h b -> DLens g a i b -> DLens (f :+: g) a (h :+: i) b
f -|-<~ g = DLens get' getd' put' putd' create' created'
    where get' (InlF x) = InlF (get f x)
          get' (InrF y) = InrF (get g y)
          getd' (InlF x) = getd f x
          getd' (InrF y) = getd g y
          put' (InlF z,InlF x) dV = InlF (put f (z,x) dV)
          put' (InlF z,InrF y) dV = InlF (create f z)
          put' (InrF w,InlF x) dV = InrF (create g w)
          put' (InrF w,InrF y) dV = InrF (put g (w,y) dV)
          putd' (InlF z) (InlF x) dV = putd f z x dV
          putd' (InlF z) (InrF y) dV = inlPosR (z,y) .~ created f z
          putd' (InrF w) (InlF x) dV = inlPosR (w,x) .~ created g w
          putd' (InrF w) (InrF y) dV = putd g w y dV
          create' (InlF z) = InlF (create f z)
          create' (InrF w) = InrF (create g w)
          created' (InlF z) = created f z
          created' (InrF w) = created g w

swap_dlns :: (Shapely f,Shapely g,ToRep f,ToRep g) => DLens (f :*: g) a (g :*: f) a
swap_dlns = nat_dlns (\a -> swap_lns)

coswap_dlns :: (Shapely f,Shapely g,ToRep f,ToRep g) => DLens (f :+: g) a (g :+: f) a
coswap_dlns = nat_dlns (\a -> coswap_lns)

distl_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens ((f :+: g) :*: h) a ((f :*: h) :+: (g :*: h)) a
distl_dlns = nat_dlns (\a -> distl_lns)

undistl_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens ((f :*: h) :+: (g :*: h)) a ((f :+: g) :*: h) a
undistl_dlns = nat_dlns (\a -> undistl_lns)

distr_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens (f :*: (g :+: h)) a ((f :*: g) :+: (f :*: h)) a
distr_dlns = nat_dlns (\a -> distr_lns)

undistr_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens ((f :*: g) :+: (f :*: h)) a (f :*: (g :+: h)) a
undistr_dlns = nat_dlns (\a -> undistr_lns)

assocl_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens (f :*: (g :*: h)) a ((f :*: g) :*: h) a
assocl_dlns = nat_dlns (\a -> assocl_lns)

assocr_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens ((f :*: g) :*: h) a (f :*: (g :*: h)) a
assocr_dlns = nat_dlns (\a -> assocr_lns)

coassocl_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens (f :+: (g :+: h)) a ((f :+: g) :+: h) a
coassocl_dlns = nat_dlns (\a -> coassocl_lns)

coassocr_dlns :: (Shapely f,Shapely g,Shapely h,ToRep f,ToRep g,ToRep h) => DLens ((f :+: g) :+: h) a (f :+: (g :+: h)) a
coassocr_dlns = nat_dlns (\a -> coassocr_lns)