我有几个类构成更广泛的层次结构的一部分,我正在尝试在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
类型签名中的relation
(Dep)和b
中的relation
都是相同。我在这里错过了什么?
答案 0 :(得分:4)
我无法解释为什么编译器无法看到关系(Dep)中的r和关系类型签名中的b都是相同的。
问题在于它们不一样。这里的问题是,relation :: (Dep a, StanfordType b) => a -> b
必须能够返回每个有效的b
。因此,虽然您对类型签名的理解是,您可以返回您(b
的作者)希望它实际意味着的任何relation
,您必须返回任何b
我( relation
)的来电者想要的。我们可以像这样明确区别(第二个变体不是实际的Haskell语法,第一个不是标准的Haskell):
relation :: forall b. (Dep a, StanfordType b) => a -> b -- Actual meaning
relation :: exists b. (Dep a, StanfordType b) => a -> b -- Your interpretation
因此,如果创建一个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
现在,解决方案可以返回StanfordType
中包含的任何ExtStanfordType
。然后,您可以像这样使用text
:
textExt :: ExtStanfordType -> Text
textExt (EST b) = text b