无法推断出两种约束类型是相同的 [英] Unable to deduce two constrained types are the same
问题描述
我有几个类构成更广泛的层次结构的一部分,我试图在 DepTag
上实现它们:
class StanfordType a where
text :: a - >文本
class StanfordType a => Dep a where
relation ::(StanfordType b)=> a - > b
data DepTag a b其中
DepTag ::(StanfordType a)=>文字 - > a - > DepTag文本a
实例StanfordType(DepTag ab)其中
text(DepTag s _)= s
实例Dep(DepTag ab)其中
关系(DepTag _ r)= r
当我尝试编译这个时,出现以下错误:
•无法从上下文推导出:b〜b1
:(a〜Text,N.StanfordType b )
由带构造函数的模式绑定:
DepTag :: forall b。 N.StanfordType b =>文字 - > b - > DepTag文本b,
在'relation'的等式中
在src / NLP / Data.hs:17:45-54
'b'是一个刚性类型变量,由
在src / NLP / Data.hs中的实例声明:17:10
'b1'是一个刚性类型变量,由
绑定,类型签名为:
relation :: forall b1。 N.StanfordType b1 => DepTag a b - > b1
at src / NLP / Data.hs:17:35
•在表达式中:r
在'relation'的等式中:relation(DepTag _ r)= r
在'N.Dep(DepTag ab)'
的实例声明中•相关绑定包括
r :: b(绑定在src / NLP / Data.hs:17:54)
关系:: DepTag ab - > b1(绑定在src / NLP / Data.hs:17:35)
我无法工作为什么编译器在关系
(Dep)和 b中看不到
是相同的。我在这里错过了什么? r
关系
的类型签名中的
我无法弄清为什么编译器无法看到两个关系中的r (Dep)和b中关系的类型签名是一样的。
问题是它们不一样。这里的问题是, relation ::(Dep a,StanfordType b)=> a - > b
必须能够返回每个有效的 b
。所以尽管你对类型签名的理解是你可以返回你(作者关系
)想要的任何 b
它实际上意味着,您必须返回我(关系的调用者)需要的任何
b
。我们可以像这样明确地区分这种区别(第二个变体不是实际的Haskell语法,第一个变体不是标准的Haskell):
关系:: forall b。 (Dep a,Stanford Type b)=> a - > b - 实际含义
关系::存在b。 (Dep a,Stanford Type b)=> a - > b - 您的解释
因此,如果要制作 Foo
,这是一个 StanfordType
的实例:
newtype Foo = Foo | Bar
实例StanfordType Foo其中
text = packFooBar
你可以现在使用GHCi进行验证,该解析实际上必须能够返回 Foo
类型的值:
> :t分辨率:: Dep a => a - > Foo
分辨率:: Dep a => a - > Foo :: Dep a => a - > Foo
当然,不可能用创建任何未知类型的值, StanfordType
实例。特别是因为每一个类型都可以有一个 StanfordType
实例。我们可以使用一个存在实际来表达第二个类型:
data ExtStanfordType where
EST :: StanfordType a => a - > ExtStanfordType
class StanfordType a => Dep a where
relation :: a - > ExtStanfordType
实例Dep(DepTag ab)其中
relation =(DepTag _ r)= EST r
现在解析可以返回包含在 ExtStanfordType
中的任何 StanfordType
。然后你可以使用 text
像这样:
textExt :: ExtStanfordType - >文本
textExt(EST b)=文本b
I have a couple of classes that form part of a wider hierarchy and I'm trying to implement them on DepTag
:
class StanfordType a where
text :: a -> Text
class StanfordType a => Dep a where
relation :: (StanfordType b) => a -> b
data DepTag a b where
DepTag :: (StanfordType a) => Text -> a -> DepTag Text a
instance StanfordType (DepTag a b) where
text (DepTag s _) = s
instance Dep (DepTag a b) where
relation (DepTag _ r) = r
When I try to compile this, I'm thrown the following error:
• Could not deduce: b ~ b1
from the context: (a ~ Text, N.StanfordType b)
bound by a pattern with constructor:
DepTag :: forall b. N.StanfordType b => Text -> b -> DepTag Text b,
in an equation for ‘relation’
at src/NLP/Data.hs:17:45-54
‘b’ is a rigid type variable bound by
the instance declaration at src/NLP/Data.hs:17:10
‘b1’ is a rigid type variable bound by
the type signature for:
relation :: forall b1. N.StanfordType b1 => DepTag a b -> b1
at src/NLP/Data.hs:17:35
• In the expression: r
In an equation for ‘relation’: relation (DepTag _ r) = r
In the instance declaration for ‘N.Dep (DepTag a b)’
• Relevant bindings include
r :: b (bound at src/NLP/Data.hs:17:54)
relation :: DepTag a b -> b1 (bound at src/NLP/Data.hs:17:35)
I can't work out why the compiler can't see that both r
in relation
(Dep) and b
in the type signature of relation
are the same. What am I missing here?
I can't work out why the compiler can't see that both r in relation (Dep) and b in the type signature of relation are the same.
The problem is that they are not the same. The problem here is, that relation :: (Dep a, StanfordType b) => a -> b
has to be able to return every valid b
. So while your understanding of the type signature is that you can return any b
that you (the writer of relation
) want it actually means, that you have to return any b
that I (the caller of relation
) want. We can make this difference explicit like this (the second variant is not actual Haskell syntax and the first is not standard Haskell):
relation :: forall b. (Dep a, StanfordType b) => a -> b -- Actual meaning
relation :: exists b. (Dep a, StanfordType b) => a -> b -- Your interpretation
So if make a type Foo
, that is an instance of StanfordType
:
newtype Foo = Foo | Bar
instance StanfordType Foo where
text = pack "FooBar"
you can now verify with GHCi, that resolution actually has to be able to return values of type Foo
:
> :t resolution :: Dep a => a -> Foo
resolution :: Dep a => a -> Foo :: Dep a => a -> Foo
Of course it is impossible to create values of any unknown type with a StanfordType
instance. Especially because literally every type can have a StanfordType
instance.
We can actually express the second type using an existential:
data ExtStanfordType where
EST :: StanfordType a => a -> ExtStanfordType
class StanfordType a => Dep a where
relation :: a -> ExtStanfordType
instance Dep (DepTag a b) where
relation = (DepTag _ r) = EST r
Now resolution can return any StanfordType
wrapped up in an ExtStanfordType
. You can then use text
like this:
textExt :: ExtStanfordType -> Text
textExt (EST b) = text b
See also: Existential type - Haskell Wiki
这篇关于无法推断出两种约束类型是相同的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!