{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Comp.Dict
( Dict (..)
, All
, withDict
, (\\)
, dictFor
, mapAll
) where
import GHC.Exts ( Constraint, Proxy#, proxy# )
import Data.Proxy ( Proxy(..) )
import Data.Vector (Vector)
import qualified Data.Vector as V
import qualified Unsafe.Coerce as U
import Data.Comp.Elem
data E (f :: k1 -> *) where
E :: f e -> E f
data Dict (c :: k -> Constraint) (a :: k) where
Dict :: c a => Dict c a
withDict :: Dict c a -> (c a => r) -> r
withDict :: forall {k} (c :: k -> Constraint) (a :: k) r.
Dict c a -> (c a => r) -> r
withDict Dict c a
Dict c a => r
x = r
c a => r
x
infixl 1 \\
(\\) :: (c a => r) -> Dict c a -> r
\\ :: forall {k} (c :: k -> Constraint) (a :: k) r.
(c a => r) -> Dict c a -> r
(\\) c a => r
x Dict c a
Dict = r
c a => r
x
class All (c :: k -> Constraint) (fs :: [k]) where
dicts :: Proxy# fs -> [E (Dict c)]
instance All c '[] where
{-# INLINE dicts #-}
dicts :: Proxy# '[] -> [E (Dict c)]
dicts Proxy# '[]
_ = []
instance (All c fs, c f) => All c (f ': fs) where
{-# INLINE dicts #-}
dicts :: Proxy# (f : fs) -> [E (Dict c)]
dicts Proxy# (f : fs)
p = Dict c f -> E (Dict c)
forall {k1} (f :: k1 -> *) (e :: k1). f e -> E f
E (Dict c f
forall {k} (c :: k -> Constraint) (a :: k). c a => Dict c a
Dict :: Dict c f) E (Dict c) -> [E (Dict c)] -> [E (Dict c)]
forall a. a -> [a] -> [a]
: (Proxy# fs -> [E (Dict c)]
forall k (c :: k -> Constraint) (fs :: [k]).
All c fs =>
Proxy# fs -> [E (Dict c)]
dicts (forall (b :: [a]) (a :: [a]). Proxy# a -> Proxy# b
forall {k} {k} (b :: k) (a :: k). Proxy# a -> Proxy# b
reproxy @fs Proxy# (f : fs)
p))
reproxy :: forall b a. Proxy# a -> Proxy# b
reproxy :: forall {k} {k} (b :: k) (a :: k). Proxy# a -> Proxy# b
reproxy Proxy# a
_ = Proxy# b
forall {k} (a :: k). Proxy# a
proxy#
dictFor :: forall c f fs. (All c fs) => Elem f fs -> Dict c f
dictFor :: forall {k} (c :: k -> Constraint) (f :: k) (fs :: [k]).
All c fs =>
Elem f fs -> Dict c f
dictFor (Elem Int
v) =
let ds :: Vector (E (Dict c))
ds = [E (Dict c)] -> Vector (E (Dict c))
forall a. [a] -> Vector a
V.fromList (Proxy# fs -> [E (Dict c)]
forall k (c :: k -> Constraint) (fs :: [k]).
All c fs =>
Proxy# fs -> [E (Dict c)]
dicts (Proxy# fs
forall {k} (a :: k). Proxy# a
proxy# :: Proxy# fs)) :: Vector (E (Dict c))
in case Vector (E (Dict c))
ds Vector (E (Dict c)) -> Int -> E (Dict c)
forall a. Vector a -> Int -> a
V.! Int
v of
E Dict c e
d -> Dict c e -> Dict c f
forall a b. a -> b
U.unsafeCoerce Dict c e
d
{-# INLINE dictFor #-}
mapAll :: forall cxt fs a. (All cxt fs) => (forall f. cxt f => Proxy f -> a) -> [a]
mapAll :: forall {k} (cxt :: k -> Constraint) (fs :: [k]) a.
All cxt fs =>
(forall (f :: k). cxt f => Proxy f -> a) -> [a]
mapAll forall (f :: k). cxt f => Proxy f -> a
v = [Dict cxt e -> a
forall (g :: k). Dict cxt g -> a
useDict Dict cxt e
d | E Dict cxt e
d <- Proxy# fs -> [E (Dict cxt)]
forall k (c :: k -> Constraint) (fs :: [k]).
All c fs =>
Proxy# fs -> [E (Dict c)]
dicts (Proxy# fs
forall {k} (a :: k). Proxy# a
proxy# :: Proxy# fs)]
where
useDict :: forall g. Dict cxt g -> a
useDict :: forall (g :: k). Dict cxt g -> a
useDict Dict cxt g
d = Dict cxt g -> (cxt g => a) -> a
forall {k} (c :: k -> Constraint) (a :: k) r.
Dict c a -> (c a => r) -> r
withDict Dict cxt g
d (Proxy g -> a
forall (f :: k). cxt f => Proxy f -> a
v (Proxy g -> a) -> Proxy g -> a
forall a b. (a -> b) -> a -> b
$ forall (t :: k). Proxy t
forall {k} (t :: k). Proxy t
Proxy @g)