{-# 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
       ) where
import GHC.Exts
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 :: Dict c a -> (c a => r) -> r
withDict Dict x :: c a => r
x = r
c a => r
x
infixl 1 \\
(\\) :: (c a => r) -> Dict c a -> r
\\ :: (c a => r) -> Dict c a -> r
(\\) x :: c a => r
x 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 _ = []
instance (All c fs, c f) => All c (f ': fs) where
  {-# INLINE dicts #-}
  dicts :: Proxy# (f : fs) -> [E (Dict c)]
dicts p :: 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 (Proxy# (f : fs) -> Proxy# fs
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 :: Proxy# a -> Proxy# b
reproxy _ = Proxy# b
forall k (a :: k). Proxy# a
proxy#
dictFor :: forall c f fs. (All c fs) => Elem f fs -> Dict c f
dictFor :: Elem f fs -> Dict c f
dictFor (Elem v :: 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 d :: Dict c e
d -> Dict c e -> Dict c f
forall a b. a -> b
U.unsafeCoerce Dict c e
d
{-# INLINE dictFor #-}