module Data.HSet
       ( HSet(..)
       , HGet(..)
       ) where
import Control.Monad.Reader
import Data.HSet.TypeLevel
data HSet (elems :: [*]) where
  HSNil  :: HSet '[]
  HSCons :: ('False ~ (Elem elem elems)) => elem -> HSet elems -> HSet (elem ': elems)
class (i ~ (Index e els)) => HGet els e i where
  
  hget :: HSet els -> e
instance HGet (e ': els) e 'Z where
  hget (HSCons e _) = e
instance (i ~ (Index e els), ('S i) ~ (Index e (e1 ': els)), HGet els e i) => HGet (e1 ': els) e ('S i) where
  hget (HSCons _ els) = hget els
type Contains els e = HGet els e (Index e els)
hask :: (MonadReader (HSet els) m, Contains els e) => m e
hask = do
  h <- ask
  return $ hget h
fun :: HSet '[Int, Double, Integer, Float]
fun = HSCons 1
      $ HSCons 2
      $ HSCons 3
      $ HSCons 4
      $ HSNil
funInt :: Int
funInt = hget fun
funDoube :: Double
funDoube = hget fun
funInteger :: Integer
funInteger = hget fun
funFloat :: Float
funFloat = hget fun
this :: (Double, Float)
this =
  let h = (,) <$> hask <*> hask
  in runReader h fun