Haskell 中实例化类型变量
编辑:已解决。我不知道在源文件中启用语言扩展并没有在 GHCi 中启用语言扩展。解决方案是在 GHCi 中 :setFlexibleContexts
。
我最近发现 Haskell 中的类和实例中的类型声明是 Horn 子句。因此,我将《Prolog 的艺术》第 3 章中的算术运算编码为 Haskell。例如:
fac(0,s(0)).
fac(s(N),F) :- fac(N,X), mult(s(N),X,F).
class Fac x y | x -> y
instance Fac Z (S Z)
instance (Fac n x, Mult (S n) x f) => Fac (S n) f
pow(s(X),0,0) :- nat(X).
pow(0,s(X),s(0)) :- nat(X).
pow(s(N),X,Y) :- pow(N,X,Z), mult(Z,X,Y).
class Pow x y z | x y -> z
instance (N n) => Pow (S n) Z Z
instance (N n) => Pow Z (S n) (S Z)
instance (Pow n x z, Mult z x y) => Pow (S n) x y
在 Prolog 中,值被实例化为证明中的(逻辑)变量。但是,我不明白如何在 Haskell 中实例化类型变量。也就是说,我不明白 Prolog 查询的 Haskell 等价物
?-f(X1,X2,...,Xn)
是什么。我认为这
:t undefined :: (f x1 x2 ... xn) => xi
会导致 Haskell 实例化 xi,但这会给出一个约束中的非类型变量参数错误,即使启用了 FlexibleContexts 也是如此。
EDIT: Solved. I was unware that enabling a language extension in the source file did not enable the language extension in GHCi. The solution was to :set FlexibleContexts
in GHCi.
I recently discovered that type declarations in classes and instances in Haskell are Horn clauses. So I encoded the arithmetic operations from The Art of Prolog, Chapter 3, into Haskell. For instance:
fac(0,s(0)).
fac(s(N),F) :- fac(N,X), mult(s(N),X,F).
class Fac x y | x -> y
instance Fac Z (S Z)
instance (Fac n x, Mult (S n) x f) => Fac (S n) f
pow(s(X),0,0) :- nat(X).
pow(0,s(X),s(0)) :- nat(X).
pow(s(N),X,Y) :- pow(N,X,Z), mult(Z,X,Y).
class Pow x y z | x y -> z
instance (N n) => Pow (S n) Z Z
instance (N n) => Pow Z (S n) (S Z)
instance (Pow n x z, Mult z x y) => Pow (S n) x y
In Prolog, values are instantiated for (logic) variable in a proof. However, I don't understand how to instantiate type variables in Haskell. That is, I don't understand what the Haskell equivalent of a Prolog query
?-f(X1,X2,...,Xn)
is. I assume that
:t undefined :: (f x1 x2 ... xn) => xi
would cause Haskell to instantiate xi
, but this gives a Non type-variable argument in the constraint
error, even with FlexibleContexts
enabled.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不确定 Prolog 示例,但我会通过以下方式在 Haskell 中定义它:
更新:
正如 danportin 在 TypeFamilies 下面的评论中指出的那样,这里不需要“惰性模式”(在实例上下文中)(他的初始代码更短且更清晰)。
不过,这种模式的一个应用,我在这个问题的上下文中可以想到的是:假设我们想将布尔逻辑添加到我们的类型级算术中:
但是由于“函数依赖项冲突”,这不会编译。
在我看来,我们仍然可以在没有fundeps的情况下表达这种重叠的情况:
这绝对不是最好的方式(它需要IncoherentInstances)。所以也许有人可以建议另一种“创伤较小”的方法。
No sure about Prolog samples, but I would define this in Haskell in the following way:
Update:
As danportin noted in his comment below TypeFamilies "Lazy pattern" (in instance context) is not needed here (his initial code is shorter and much cleaner).
One application of this pattern though, which I can think of in the context of this question is this: Say we want to add Boolean logic to our type-level arithmetic:
But this will not compile due to "Functional dependencies conflict".
And it looks to me that we still can express this overlapping case without fundeps:
It's definitely not a nicest way (it requires IncoherentInstances). So maybe somebody can suggest another, less 'traumatic' approach.