{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Vinyl.Lens
( RecElem(..)
, RElem
, RecSubset(..)
, RSubset
, REquivalent
, type (∈)
, type (⊆)
, type (≅)
, type (<:)
, type (:~:)
) where
import Data.Vinyl.Core
import Data.Vinyl.Functor
import Data.Vinyl.TypeLevel
import Data.Typeable (Proxy(..))
class i ~ RIndex r rs => RecElem record (r :: k) (rs :: [k]) (i :: Nat) where
rlens
:: Functor g
=> sing r
-> (f r -> g (f r))
-> record f rs
-> g (record f rs)
rget
:: sing r
-> record f rs
-> f r
rput
:: f r
-> record f rs
-> record f rs
type RElem = RecElem Rec
lens
:: Functor f
=> (s -> a)
-> (s -> b -> t)
-> (a -> f b)
-> s
-> f t
lens sa sbt afb s = fmap (sbt s) $ afb (sa s)
{-# INLINE lens #-}
instance RecElem Rec r (r ': rs) 'Z where
rlens _ f (x :& xs) = fmap (:& xs) (f x)
{-# INLINE rlens #-}
rget k = getConst . rlens k Const
{-# INLINE rget #-}
rput y = getIdentity . rlens Proxy (\_ -> Identity y)
{-# INLINE rput #-}
instance (RIndex r (s ': rs) ~ 'S i, RElem r rs i) => RecElem Rec r (s ': rs) ('S i) where
rlens p f (x :& xs) = fmap (x :&) (rlens p f xs)
{-# INLINE rlens #-}
rget k = getConst . rlens k Const
{-# INLINE rget #-}
rput y = getIdentity . rlens Proxy (\_ -> Identity y)
{-# INLINE rput #-}
class is ~ RImage rs ss => RecSubset record (rs :: [k]) (ss :: [k]) is where
rsubset
:: Functor g
=> (record f rs -> g (record f rs))
-> record f ss
-> g (record f ss)
rcast
:: record f ss
-> record f rs
rcast = getConst . rsubset Const
{-# INLINE rcast #-}
rreplace
:: record f rs
-> record f ss
-> record f ss
rreplace rs = getIdentity . rsubset (\_ -> Identity rs)
{-# INLINE rreplace #-}
type RSubset = RecSubset Rec
instance RecSubset Rec '[] ss '[] where
rsubset = lens (const RNil) const
instance (RElem r ss i , RSubset rs ss is) => RecSubset Rec (r ': rs) ss (i ': is) where
rsubset = lens (\ss -> rget Proxy ss :& rcast ss) set
where
set :: Rec f ss -> Rec f (r ': rs) -> Rec f ss
set ss (r :& rs) = rput r $ rreplace rs ss
type REquivalent rs ss is js = (RSubset rs ss is, RSubset ss rs js)
type r ∈ rs = RElem r rs (RIndex r rs)
type rs ⊆ ss = RSubset rs ss (RImage rs ss)
type rs ≅ ss = REquivalent rs ss (RImage rs ss) (RImage ss rs)
type rs <: ss = rs ⊆ ss
type rs :~: ss = rs ≅ ss