问题
在Haskell中考虑以下设计问题。我有一个简单的符号EDSL,我想在其中表达变量和一般表达式(多元多项式),例如x^2 * y + 2*z + 1
。另外,我想在表达式(例如x^2 + 1 = 1
)和定义(例如)上表达某些符号方程式x := 2*y - 2
。
目标是:
- 变量和通用表达式具有单独的类型-某些函数可能会应用于变量,而不是复杂的表达式。例如,定义运算符
:=
可能是类型,(:=) :: Variable -> Expression -> Definition
并且不应该将复杂的表达式作为其左侧参数传递(尽管应该可以将变量作为其右侧参数传递,而无需显式转换) 。 - 将表达式作为的实例
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
因为:=
应该给出变量的定义而不是整个左侧表达式。
我不确定
—
Maciej Bendkowski
FromVar
类型类将如何提供帮助。我想在保留Expr
的实例时避免显式强制转换Num
。我对问题进行了编辑,并添加了一个我想实现的表示法示例。
class FromVar e
一个方法fromVar :: Variable -> e
,并为提供实例Expression
和Variable
,然后让你的变量具有多态类型x :: FromVar e => e
等等。我还没有测试有多好这个工作,因为我在我的手机现在。