Haskell中的隐式静态类型强制转换(强制)


9

问题

在Haskell中考虑以下设计问题。我有一个简单的符号EDSL,我想在其中表达变量和一般表达式(多元多项式),例如x^2 * y + 2*z + 1。另外,我想在表达式(例如x^2 + 1 = 1)和定义(例如)上表达某些符号方程式x := 2*y - 2

目标是:

  1. 变量和通用表达式具有单独的类型-某些函数可能会应用于变量,而不是复杂的表达式。例如,定义运算符:=可能是类型, (:=) :: Variable -> Expression -> Definition并且不应该将复杂的表达式作为其左侧参数传递(尽管应该可以将变量作为其右侧参数传递,而无需显式转换) 。
  2. 将表达式作为的实例Num,这样就可以将整数文字提升为表达式,并为常见的代数运算(如加法或乘法)使用方便的表示法,而无需引入一些辅助包装运算符。

换句话说,我希望对表达式进行变量的隐式静态类型转换(强制转换)。现在,我知道这样,Haskell中没有隐式类型强制转换。但是,某些面向对象的编程概念(在这种情况下为简单继承)可以在Haskell的类型系统中表达,无论有没有语言扩展。如何在保持轻量级语法的同时满足以上两个条件?可能吗

讨论区

显然,这里的主要问题是Num类型限制,例如

(+) :: Num a => a -> a -> a

原则上,可以为变量和表达式编写单个(通用)代数数据类型。然后,可以这样写:=:区分左侧表达式,只接受变量构造函数,否则会出现运行时错误。但是,这不是一个干净的静态(即编译时)解决方案...

理想情况下,我想实现一种轻量级语法,例如

computation = do
  x <- variable
  t <- variable

  t |:=| x^2 - 1
  solve (t |==| 0)

特别是,我想禁止使用符号, t + 1 |:=| x^2 - 1因为:=应该给出变量的定义而不是整个左侧表达式。


1
也许你可以使用class FromVar e一个方法fromVar :: Variable -> e,并为提供实例ExpressionVariable,然后让你的变量具有多态类型x :: FromVar e => e等等。我还没有测试有多好这个工作,因为我在我的手机现在。
Mor A.

我不确定FromVar类型类将如何提供帮助。我想在保留Expr的实例时避免显式强制转换Num。我对问题进行了编辑,并添加了一个我想实现的表示法示例。
Maciej Bendkowski

Answers:


8

要利用多态性而不是子类型化(因为这是Haskell中的全部功能),请不要认为“变量就是表达式”,而是“变量和表达式都具有某些共同的操作”。这些操作可以放在类型类中:

class HasVar e where fromVar :: Variable -> e

instance HasVar Variable where fromVar = id
instance HasVar Expression where ...

然后,使事物多态,而不是投射事物。如果您有v :: forall e. HasVar e => e,它既可以用作表达式也可以用作变量。

example :: (forall e. HasVar e => e) -> Definition
example v = (v := v)  -- v can be used as both Variable and Expression

 where

  (:=) :: Variable -> Expression -> Definition

进行以下类型检查的代码的骨架:https ://gist.github.com/Lysxia/da30abac357deb7981412f1faf0d2103

computation :: Solver ()
computation = do
  V x <- variable
  V t <- variable
  t |:=| x^2 - 1
  solve (t |==| 0)

有趣,谢谢!我考虑过一会儿将变量和表达式都隐藏在存在性类型后面,但是我拒绝了这个想法,因为它引入了附加的符号,请参见V。最初不是我想要的,但是也许我赶不上了……也许我不能摆脱不透明的东西V。在相关说明中,如何创建的实例V (forall e . HasVar e => e)?在Coq中,我将对归纳类型使用类型计算和模式匹配,但尚不清楚如何在Haskell中实现该功能。
Maciej Bendkowski

1
您可以以w :: Variable某种方式获取并申请fromVarvariable = (\w -> V (fromVar w)) <$> (_TODO_ :: Solver Variable)
李,姚夏

1
并且V可以与impredicative类型是可以避免的,但是这仍然WIP。或者,我们可以variable显式地采用多态参数作为延续,而不是通过来间接实现(>>=)
夏丽瑶
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.