Haskell类型族错误

5

抱歉打扰您,这是一个简单的问题。我正在尝试学习类型家族扩展的工作原理。当我调试它时,遇到了一个错误,但我无法弄清楚原因。

class Foo a b c where
    data T a b c :: *

    f :: a -> T a b c

    g :: T a b c -> b

    h :: c -> a -> b
    h c a = g $ f a

错误信息:

    Could not deduce (Foo a b c0) arising from a use of ‘g’
from the context (Foo a b c)
  bound by the class declaration for ‘Foo’
  at DB/Internal/Typecast.hs:(17,1)-(25,19)
The type variable ‘c0’ is ambiguous
Relevant bindings include
  a :: a (bound at DB/Internal/Typecast.hs:25:9)
  h :: c -> a -> b (bound at DB/Internal/Typecast.hs:25:5)
In the expression: g
In the expression: g $ f a
In an equation for ‘h’: h c a = g $ f a

我不明白为什么在 T a b c 中使用 g 时,c 是模糊的。编译器不能从 fT a b c 中获取 c 的类型吗?

我只想要 g . f 的组合。


请修正您代码示例中的缩进 - 也就是说,请发布您实际使用的代码。发布与实际问题不相关的代码只会混淆问题的本质。 - Cubic
1
“编译器不能从 fT a b c 获取 c 的类型吗?” “可以,但是 f 又从哪里获取其 T a b c 呢?” - Daniel Wagner
@DanielWagner 抱歉,我不认为我理解类型族如何工作。在使用data关键字的实例声明中,f和g中的T a b c不是我声明的吗? - Larry
1个回答

4
请注意,在这个定义中。
h :: c -> a -> b
h c a = g $ f a

没有限制fg引用您为其定义h的相同实例。 (这种灵活性通常有助于定义实例。)

从类型推断中,g的结果被限制为与b相同的类型,并且f的参数被限制为a的类型,但是并没有说明从T a b c传递给另一个所使用的c是相同的!

在这种情况下修复此问题,您可以启用ScopedTypeVariables并执行以下操作:

    h c a = g (f a :: T a b c)

请注意,这是因为数据族是“可逆的”(可以从最终类型推断出数据族的类型参数)。如果您使用了一个类型族,即使是这个也不会起作用,因为T a b c并不能确定c

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接