lundi 17 décembre 2018

How to (unsafely) reflect a map as a constraint?

I want a typeclass that represents membership in a reified Data.Map.Map. So something like:

class Reifies s (Map Text v) => IsMember (x :: Symbol) s where
  value :: Proxy s -> Proxy x -> v

And then I would like to implement a function which returns a Dict instance of this class whenever a symbol is present:

checkMember :: forall s x v. Reifies s (Map Text v)
  => SSymbol x -> Maybe (Dict (IsMember x s))
checkMember sx =
  let m = reflect (Proxy @s)
  in  (_ :: v -> Dict (IsMember x s)) <$> Map.lookup (fromSing sx) m

I don't mind using unsafeCoerce to implement checkMember, but even so I'm having trouble figuring out how to do this (fill in the type hole).


Approximate preamble:

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}

import Data.Constraint(Dict(..))
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Reflection (Reifies, reflect)
import Data.Singletons (fromSing)
import Data.Singletons.TypeLits (SSymbol, Symbol)





Aucun commentaire:

Enregistrer un commentaire