我正在尝试使用类型族表示表达式,但我似乎无法想出我想要写的约束条件,而且我开始觉得这似乎不可能。以下是我的代码:
class Evaluable c where
type Return c :: *
evaluate :: c -> Return c
data Negate n = Negate n
instance (Evaluable n, Return n ~ Int) => Evaluable (Negate n) where
type Return (Negate n) = Return n
evaluate (Negate n) = negate (evaluate n)
这一切都编译得很好,但它并没有完全表达我想要的。在 Negate
实例的 Evaluable
约束中,我说 Negate
内部表达式的返回类型必须是一个 Int
(使用 Return n ~ Int
),这样我才能对其调用 negate,但这太过严格了。实际上,返回类型只需要是 Num
类型类的一个实例,该类型类具有 negate
函数。这样,Double
、Integer
或任何其他 Num
的实例也可以被否定,而不仅仅是 Int
。但我不能只写
Return n ~ Num
相反,因为Num
是一个类型类而Return n
是一个类型。我也不能放置。
Num (Return n)
Return n
是一个类型而非类型变量,所以不能这么用。在 Haskell 中是否有实现的可能?如果没有,是否应该有这样的实现,还是我理解有误?我感觉 Java 可以添加这样的约束。如果问题不够清晰,请告诉我。
编辑:谢谢大家的回答,它们有帮助并且指出了我的疑惑。似乎类型检查器不能处理我想要做的事情,除非使用 UndecidableInstances。那么我的问题是,我想要表达的内容是否真的是不可判定的?对于更高级的类型检查器来说,是否存在一种约束条件,可以检查“Return n 是否为 Num 的实例”这一点,从而变得可判定?
FlexibleContexts
之类的语言扩展?因为我相当确定它确实这样做了——只是关于_Haskell究竟能否实现这一点_的副注。 - Erik Kaplun