{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Row.Dictionaries
(
uniqueMap, uniqueAp, uniqueApSingle, uniqueZip
, extendHas, mapHas, apHas, apSingleHas
, mapExtendSwap, apExtendSwap, apSingleExtendSwap, zipExtendSwap
, FreeForall
, FreeBiForall
, freeForall
, mapForall
, apSingleForall
, IsA(..)
, As(..)
, ActsOn(..)
, As'(..)
, Dict(..), (:-)(..), HasDict(..), (\\), withDict
, Unconstrained, Unconstrained1, Unconstrained2
)
where
import Data.Constraint
import Data.Functor.Const
import Data.Proxy
import qualified Unsafe.Coerce as UNSAFE
import GHC.TypeLits
import Data.Row.Internal
data As c f a where
As :: forall c f a t. (a ~ f t, c t) => As c f a
class IsA c f a where
as :: As c f a
instance c a => IsA c f (f a) where
as = As
data As' c t a where
As' :: forall c f a t. (a ~ f t, c f) => As' c t a
class ActsOn c t a where
actsOn :: As' c t a
instance c f => ActsOn c t (f t) where
actsOn = As'
newtype MapForall c f (r :: Row k) = MapForall { unMapForall :: Dict (Forall (Map f r) (IsA c f)) }
newtype ApSingleForall c a (fs :: Row (k -> k')) = ApSingleForall
{ unApSingleForall :: Dict (Forall (ApSingle fs a) (ActsOn c a)) }
mapForall :: forall f ρ c. Forall ρ c :- Forall (Map f ρ) (IsA c f)
mapForall = Sub $ unMapForall $ metamorph @_ @ρ @c @Const @Proxy @(MapForall c f) @Proxy Proxy empty uncons cons $ Proxy
where empty _ = MapForall Dict
uncons _ _ = Const Proxy
cons :: forall ℓ τ ρ. (KnownSymbol ℓ, c τ, FrontExtends ℓ τ ρ, AllUniqueLabels (Extend ℓ τ ρ))
=> Label ℓ -> Const (MapForall c f ρ) (Proxy τ)
-> MapForall c f (Extend ℓ τ ρ)
cons _ (Const (MapForall Dict)) = case frontExtendsDict @ℓ @τ @ρ of
FrontExtendsDict Dict -> MapForall Dict
\\ mapExtendSwap @f @ℓ @τ @ρ
\\ uniqueMap @f @(Extend ℓ τ ρ)
apSingleForall :: forall a fs c. Forall fs c :- Forall (ApSingle fs a) (ActsOn c a)
apSingleForall = Sub $ unApSingleForall $ metamorph @_ @fs @c @Const @Proxy @(ApSingleForall c a) @Proxy Proxy empty uncons cons $ Proxy
where empty _ = ApSingleForall Dict
uncons _ _ = Const Proxy
cons :: forall ℓ τ ρ. (KnownSymbol ℓ, c τ, FrontExtends ℓ τ ρ, AllUniqueLabels (Extend ℓ τ ρ))
=> Label ℓ -> Const (ApSingleForall c a ρ) (Proxy τ)
-> ApSingleForall c a (Extend ℓ τ ρ)
cons _ (Const (ApSingleForall Dict)) = case frontExtendsDict @ℓ @τ @ρ of
FrontExtendsDict Dict -> ApSingleForall Dict
\\ apSingleExtendSwap @a @ℓ @τ @ρ
\\ uniqueApSingle @a @(Extend ℓ τ ρ)
freeForall :: forall r c. Forall r c :- Forall r Unconstrained1
freeForall = Sub $ UNSAFE.unsafeCoerce @(Dict (Forall r c)) Dict
type FreeForall r = Forall r Unconstrained1
type FreeBiForall r1 r2 = BiForall r1 r2 Unconstrained2
extendHas :: forall l t r. Dict (Extend l t r .! l ≈ t)
extendHas = UNSAFE.unsafeCoerce $ Dict @Unconstrained
mapHas :: forall f l t r. (r .! l ≈ t) :- (Map f r .! l ≈ f t, Map f r .- l ≈ Map f (r .- l))
mapHas = Sub $ UNSAFE.unsafeCoerce $ Dict @(r .! l ≈ t)
apHas :: forall l f ϕ t ρ. (ϕ .! l ≈ f, ρ .! l ≈ t) :- (Ap ϕ ρ .! l ≈ f t, Ap ϕ ρ .- l ≈ Ap (ϕ .- l) (ρ .- l))
apHas = Sub $ UNSAFE.unsafeCoerce $ Dict @(ϕ .! l ≈ f, ρ .! l ≈ t)
apSingleHas :: forall x l f r. (r .! l ≈ f) :- (ApSingle r x .! l ≈ f x, ApSingle r x .- l ≈ ApSingle (r .- l) x)
apSingleHas = Sub $ UNSAFE.unsafeCoerce $ Dict @(r .! l ≈ f)
mapExtendSwap :: forall f ℓ τ r. Dict (Extend ℓ (f τ) (Map f r) ≈ Map f (Extend ℓ τ r))
mapExtendSwap = UNSAFE.unsafeCoerce $ Dict @Unconstrained
apExtendSwap :: forall ℓ f fs τ r. Dict (Extend ℓ (f τ) (Ap fs r) ≈ Ap (Extend ℓ f fs) (Extend ℓ τ r))
apExtendSwap = UNSAFE.unsafeCoerce $ Dict @Unconstrained
apSingleExtendSwap :: forall τ ℓ f r. Dict (Extend ℓ (f τ) (ApSingle r τ) ≈ ApSingle (Extend ℓ f r) τ)
apSingleExtendSwap = UNSAFE.unsafeCoerce $ Dict @Unconstrained
zipExtendSwap :: forall ℓ τ1 r1 τ2 r2. Dict (Extend ℓ (τ1, τ2) (Zip r1 r2) ≈ Zip (Extend ℓ τ1 r1) (Extend ℓ τ2 r2))
zipExtendSwap = UNSAFE.unsafeCoerce $ Dict @Unconstrained
uniqueMap :: forall f r. Dict (AllUniqueLabels (Map f r) ≈ AllUniqueLabels r)
uniqueMap = UNSAFE.unsafeCoerce $ Dict @Unconstrained
uniqueAp :: forall fs r. Dict (AllUniqueLabels (Ap fs r) ≈ AllUniqueLabels r)
uniqueAp = UNSAFE.unsafeCoerce $ Dict @Unconstrained
uniqueApSingle :: forall x r. Dict (AllUniqueLabels (ApSingle r x) ≈ AllUniqueLabels r)
uniqueApSingle = UNSAFE.unsafeCoerce $ Dict @Unconstrained
uniqueZip :: forall r1 r2. Dict (AllUniqueLabels (Zip r1 r2) ≈ (AllUniqueLabels r1, AllUniqueLabels r2))
uniqueZip = UNSAFE.unsafeCoerce $ Dict @Unconstrained