I get an error
app\Main.hs:1:1: error:
Couldn't match kind `*' with `Constraint'
When matching types
b :: *
(Set b, Set s) :: Constraint
|
1 | {-# LANGUAGE TypeFamilies #-}
| ^
I don't know why b
and the constraint (Set b, Set s)
are being matched?
I would expect the constraint to existentially quantify the type b but why would it be matching them?
I believe the last thing I changed before getting the error was adding OpOutcome to the class.
here is the code
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableSuperClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE RankNTypes #-}
module Main where
import GHC.TypeLits (Symbol)
import GHC.Exts (Constraint)
import Data.Reflection (Reifies, reflect)
import Data.Proxy (Proxy(..))
main :: IO ()
main = print 5
class ((a,b)::Constraint) => HasCtxt a b
instance (a,b) => HasCtxt a b
class Determines a b | a -> b
instance Determines a b => Determines a b
type Set b = (b ~ b)
type OpLayout a = (forall s ctxt b. (OpCtxt a s b ~ ctxt, Determines a b, Determines a ctxt,Reifies s b) => ( HasCtxt ctxt (Reifies s b))) :: Constraint
data Stack a where
Cons :: OpConstructor a -> Stack b -> Stack a
Nil :: Stack "NIL"
class OpLayout a => OpCode (a::Symbol) where
type OpCtxt a s b = (ctxt :: Constraint) | ctxt -> s b
type OpOutcome a :: *
data OpConstructor a
opValue :: Determines a s => Proxy s
opValue = Proxy
popOP :: OpCtxt a s b => Stack a -> (b :: *)
evalOP :: OpConstructor a -> Stack x -> OpOutcome a
instance OpCode "load_val" where
type OpCtxt "load_val" s b = (Set s, Set b)
type OpOutcome "load_val" = Stack "load_val"
data OpConstructor "load_val" = forall b. LOAD_VAL b
popOP stack = reflect opValue
evalOP op stack = op `Cons` stack
edit: smaller version, thanks to Krzysztof Gogolewski
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE PolyKinds #-}
module Err where
import GHC.Exts (Constraint)
class Determines b | -> b
class (forall (b :: *) (c :: Constraint). (Determines b, Determines c) => c) => OpCode
instance OpCode
Here's a much smaller file that has essentially the same error:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE FlexibleContexts #-}
module Test where
import GHC.Exts (Constraint)
class Determines a b | a -> b
class (forall ctxt. (Determines a a, Determines a (OpCtxt a)) => ctxt) => OpCode a where
type OpCtxt a :: Constraint
instance OpCode ()
This gives:
test.hs:1:1: error:
Couldn't match kind ‘Constraint’ with ‘*’
When matching types
OpCtxt () :: Constraint
() :: *
|
1 | {-# LANGUAGE TypeFamilies #-}
| ^
(By the way, in the future, you should probably try to do some similar minization yourself before asking on here.)
It's certainly a bug that GHC reports the error with such unhelpful location information. However, there's now so few places for a problem to lurk that we can have a pretty good idea what's happening. The situation here is that we are asking for
Determines a a
Determines a (OpCtxt a)
with a functional dependency in scope that says a
should be enough to work out the other argument to Determines
. Well, we know a
has *
, because we're writing instance OpCode ()
and () :: *
; and we know OpCtxt a
has kind Constraint
, because we said so in the class declaration. So GHC gives up on trying to unify a
and OpCtxt a
before it even gets started -- they don't have the same kinds, so can't be equal!
The only trick you need left to see why you get the exact error message you do is to stick ()
for a
everywhere (because that's the instance we're trying to write).
Translating back to your setting: you ask for
Determines a b
Determines a ctxt
where we know b :: *
because it appears as the second argument to Reifies :: k -> * -> Constraint
, and we know ctxt :: Constraint
because we said so in the OpCode
class declaration. So the functional dependency can't possibly work out right. Then you get the error you saw by putting OpCtxt "load_val" s b
for ctxt
, and then reducing to (Set s, Set b)
.