[英]Unhelpful Kind equality error at the start of file
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?我不知道为什么b
和约束(Set b, Set s)
被匹配? I would expect the constraint to existentially quantify the type b but why would it be matching them?我希望约束能够存在性地量化 b 类型,但为什么它会匹配它们呢?
I believe the last thing I changed before getting the error was adding OpOutcome to the class.我相信在收到错误之前我更改的最后一件事是将 OpOutcome 添加到 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编辑:更小的版本,感谢 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. GHC 使用这种无用的位置信息报告错误肯定是一个错误。 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
.在Determines
中具有函数依赖关系,它表示a
应该足以计算出的另一个参数。 Well, we know a
has *
, because we're writing instance OpCode ()
and ():: *
;好吧,我们知道a
有*
,因为我们正在编写instance OpCode ()
和():: *
; and we know OpCtxt a
has kind Constraint
, because we said so in the class declaration.我们知道OpCtxt a
有一种Constraint
,因为我们在 class 声明中这么说。 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!所以 GHC 甚至在开始之前就放弃了尝试统一a
和OpCtxt a
——它们没有相同的种类,所以不能相等!
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).要查看为什么会收到您所做的确切错误消息,您需要留下的唯一技巧是将()
粘贴a
任何地方(因为这是我们正在尝试编写的实例)。
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.我们知道b:: *
因为它作为Reifies:: k -> * -> Constraint
的第二个参数出现,我们知道ctxt:: Constraint
因为我们在OpCode
class 声明中这么说。 So the functional dependency can't possibly work out right.所以函数依赖不可能正确解决。 Then you get the error you saw by putting OpCtxt "load_val" sb
for ctxt
, and then reducing to (Set s, Set b)
.然后,您通过将OpCtxt "load_val" sb
ctxt
,然后减少到(Set s, Set b)
来得到您看到的错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.