无法推断出两种约束类型是相同的 [英] Unable to deduce two constrained types are the same

查看:120
本文介绍了无法推断出两种约束类型是相同的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个类构成更广泛的层次结构的一部分,我试图在 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

另见:存在类型 - Haskell Wiki


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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆