我想用类型系列来表示表达式,但我似乎无法弄清楚如何编写我想要的约束,并且我开始觉得它是不可能的。这里是我的代码:Haskell类型家族实例类型约束
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
类型类的实例。那样Double
s,Integer
s或Num
的任何其他实例也可以被否定,而不仅仅是Int
s。但我不能只写
Return n ~ Num
,而不是因为Num
是一种类和Return n
是一种类型。我也不能把
Num (Return n)
,而不是因为Return n
是一种不是一个类型的变量。
我试图做什么甚至可能与Haskell?如果不是,应该是,还是我误解了它背后的一些理论?我觉得Java可以添加这样的约束。让我知道这个问题是否可以更清楚。
编辑:谢谢你们,这些回应正在帮助我,并且正在接受我怀疑的事情。看起来,类型检查器无法处理我想要做的事情,如果没有UndecidableInstances,所以我的问题是,我想表达的是真正不可判定的?这是对Haskell编译器的,但它是一般的吗?即,是否还存在一个约束,意思是“检查Return n是Num的一个实例”,它是可判定为更高级的类型检查器的约束?
顺便说一句,没有GHC曾经推荐的语言扩展,如eg 'FlexibleContexts'或其他什么,在你的试错过程中?因为我确信它确实 - 只是关于_的旁注 - “Haskell甚至可能”__位。 –