-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make reify polykinded #34
Comments
What's the use case for this? |
I'm not sure if this is what @treeowl originally had in mind. I have a small proof of concept library here, where reify :: Reifiable a => a -> (forall (s :: ReifyKind a). ReifyConstraint a s => Proxy s -> r) -> r The interesting point is that some kinds, e.g. It allows one to write stuff like program :: forall s t. (ReifyComparable s t, Reifies s Integer, Reifies t Integer)
=> Proxy s -> Modulus s -> Proxy t -> Modulus t -> Integer
program tokenn valuen tokenm valuem =
case testSameReification tokenn tokenm of
Just Refl -> unMod (valuen + valuem)
Nothing -> -1 and uniformly handles the currently four different Again, it's only a proof of concept and I'm not sure how good of a real-world use case this actually is. |
I didn't have any particular application in mind. It just seemed a bit weird to restrict the kind. The downside of generalization, theoretically, is that if future Haskell has |
It's my first attempt to use this library, so it is likely that I am doing something wrong. But from the original problem description it also looks like I hit exactly this problem in a real usecase. I am trying to describe a 'schemas' with types (something like the servant does for the web API). The problem I am trying to solve with this library is to be able to select schema at runtime (for example a user preference) and still use type safe functions. Here is a simplified example ( {-# LANGUAGE DataKinds #-}
import Data.Proxy
import Data.Reflection
import GHC.TypeLits
-- | Schema shape
data TL = TL Nat Nat -- type level schema
data VL = VL Int Integer -- value leval schema
-- | Convert schema from type level to value level
instance (KnownNat m, KnownNat n) => Reifies ('TL m n) VL where
reflect _proxy = VL (fromIntegral $ natVal (Proxy @m)) (natVal (Proxy @n))
-- | Concrete schema examples, defined as types
type T1 = 'TL 1 0
type T2 = 'TL 2 3
type T3 = 'TL 3 0
-- ... more schemas are possible
-- | Data type for actual data
data Item (t :: TL) = Item [Integer] deriving Show
-- | Example type safe function to create item of requested type.
mkItem :: forall t. Reifies t VL => Item t
mkItem =
let (VL a b) = reflect (Proxy @t)
in Item (replicate a b)
main :: IO ()
main = do
print (Item [0] :: Item T1) -- manually create item
print (mkItem @T1) -- item created by concrete type
-- Create item in a type safe way (using mkItem), but
-- depending on some run-time value 'sch'.
let sch :: VL
sch = reflect @T1 Proxy
reify sch (\(p :: Proxy t) -> print (mkItem @t)) The error is:
Is this the same problem? I appreciate any suggestion. |
I just came across this issue myself, and I am also inclined to agree that it makes more sense for Historically, I think the reason this wasn't the case is because you would have to define newtype Magic a r k = Magic (forall (s :: k). Reifies s a => Proxy s -> r) And this simply wasn't possible prior to the introduction of Another hiccup is that it's not clear to me how to make the API in the |
@RyanGlScott is there any quick fix possible to the library, such that I could run the example above and maybe some more experiments? It is OK if it's on a separate branch/fork, until all the details are sorted out. |
I've pushed a branch to |
@RyanGlScott , thanks. |
Currently, we have
I believe we probably want something more like
I have no particular opinion on the order of the type variables. Is there some fundamental reason this won't work? Is there some fundamental reason it's not desirable?
The text was updated successfully, but these errors were encountered: