Haskell 无法推断两个受约束类型是相同的
我有几个类构成了更广泛层次结构的一部分,我正试图在Haskell 无法推断两个受约束类型是相同的,haskell,Haskell,我有几个类构成了更广泛层次结构的一部分,我正试图在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
上实现它们:
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
当我试图编译此文件时,会抛出以下错误:
• 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)
我不明白为什么编译器看不到关系中的r
(Dep)和关系的类型签名中的b
是相同的。我错过了什么
我不明白为什么编译器看不到关系中的r(Dep)和关系的类型签名中的b是相同的
问题是它们不一样。这里的问题是,关系::(Dep a,StanfordType b)=>a->b
必须能够返回每个有效的b
。因此,虽然您对类型签名的理解是,您可以返回您(关系的编写者)想要的任何b
,但实际上这意味着您必须返回我(关系的调用方)想要的任何b
。我们可以这样明确地区别(第二种变体不是实际的Haskell语法,第一种不是标准的Haskell语法):
因此,如果生成一个类型Foo
,这就是StanfordType
的一个实例:
newtype Foo = Foo | Bar
instance StanfordType Foo where
text = pack "FooBar"
现在,您可以使用GHCi验证,解析实际上必须能够返回类型为Foo
的值:
> :t resolution :: Dep a => a -> Foo
resolution :: 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
instance Dep (DepTag a b) where
relation = (DepTag _ r) = EST r
现在resolution可以返回任何封装在ExtStanfordType
中的StanfordType
。然后可以像这样使用text
:
textExt :: ExtStanfordType -> Text
textExt (EST b) = text b
另见:
我不明白为什么编译器看不到关系中的r(Dep)和关系的类型签名中的b是相同的
问题是它们不一样。这里的问题是,关系::(Dep a,StanfordType b)=>a->b
必须能够返回每个有效的b
。因此,虽然您对类型签名的理解是,您可以返回您(关系的编写者)想要的任何b
,但实际上这意味着您必须返回我(关系的调用方)想要的任何b
。我们可以这样明确地区别(第二种变体不是实际的Haskell语法,第一种不是标准的Haskell语法):
因此,如果生成一个类型Foo
,这就是StanfordType
的一个实例:
newtype Foo = Foo | Bar
instance StanfordType Foo where
text = pack "FooBar"
现在,您可以使用GHCi验证,解析实际上必须能够返回类型为Foo
的值:
> :t resolution :: Dep a => a -> Foo
resolution :: 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
instance Dep (DepTag a b) where
relation = (DepTag _ r) = EST r
现在resolution可以返回任何封装在ExtStanfordType
中的StanfordType
。然后可以像这样使用text
:
textExt :: ExtStanfordType -> Text
textExt (EST b) = text b
另请参见:我不知道如何实现关系
。StanfordType基本上只是Show
,但是带有Text
,因此关系几乎是(Dep a,Show b)=>a->b
。您想如何快速生成任何showt=>t
值?这似乎几乎是不可能的。就像实现一个(total)函数a->b
。编译器无法计算出它们是相同的,因为它们不是。Dep
定义中的类型变量与DepTag
@jpath定义中的b
不同,我肯定遗漏了一些东西,因为我不明白它们为什么不一样DepTag
有两个参数,我认为第二个参数被限制为StanfordType
的成员。函数关系
还返回一个值,该值被限制为StanfordType
的成员。我遗漏了什么?b
可以是斯坦福类型的任何成员。因此,如果我创建一个类型Foo
,并使其成为StandfordType
的成员。然后relation
必须能够快速生成Foo
s,因为relation::Dep a=>a->Foo
是relation
的有效实例化。你能给我一个有效的Foo
值吗?谢谢你的帮助,不过我还是不太明白。如果我决定实现1000个StanfordType
,我不明白它们是如何影响关系的。只要relation
能够返回StanfordType
的1000个成员中的至少一个,不是吗?我不知道如何实现relation
。StanfordType基本上只是Show
,但是带有Text
,因此关系几乎是(Dep a,Show b)=>a->b
。您想如何快速生成任何showt=>t
值?这似乎几乎是不可能的。就像实现一个(total)函数a->b
。编译器无法计算出它们是相同的,因为它们不是。Dep
定义中的类型变量与DepTag
@jpath定义中的b
不同,我肯定遗漏了一些东西,因为我不明白它们为什么不一样DepTag
有两个参数,我认为第二个参数被限制为StanfordType
的成员。函数关系
还返回一个值,该值被限制为StanfordType
的成员。我遗漏了什么?b
可以是斯坦福类型的任何成员。因此,如果我创建一个类型Foo
,并使其成为StandfordType
的成员。然后必须设置关系