省略数据类型构造函数

时间:2016-11-30 00:06:03

标签: haskell types

我试图在Haskell中实现以下功能:

0,1,2,...:N  
x,y,z,...:V  
+,*,-,/,...:F    
F alias for Expr -> Expr -> Expr  
Expr := N|V|F Expr Expr

我的问题首先是:
语法是否在类型级别存在缺陷?这有意义吗?所有术语看起来都是类型检查(允许0,1,...同时是Expr和N子类型,x,y,...是Expr和V子类型。)

其次,最接近的Haskell实现是什么?我目前的Haskell实现是:

data F = +|-|*|... 
data Expr = N|V|MakeExpr F Expr Expr

有什么建议吗?

编辑 -

语法和实现之间的关键区别在于语法中隐式/省略了类型构造函数。为什么Haskell中的类型构造函数是强制的?

1 个答案:

答案 0 :(得分:2)

  

语法和实现之间的关键区别在于语法中隐式/省略了类型构造函数。为什么Haskell中的类型构造函数是强制的?

  

语法是否在类型级别存在缺陷?是否有意义?所有术语看起来都是类型检查(允许0,1,...同时是Expr和N子类型,x,y,...是Expr和V子类型

数据构造函数 1 在Haskell中是必需的具体,以确保不能具有x,y ,. 。是Expr和V亚型。

因此,您的语法看起来像是您希望语言术语如何工作的合理模型。但是,作为一种直接设计,你想要将你的语言术语表示为Haskell数据类型是没有意义的。

基本上,Haskell故意没有子类型。它确保在您创建新类型(使用newtypedata)时,新类型的所有值都与所有其他现有类型的值(以及将创建的所有类型)不同在未来)。它通过使用户定义类型的值总是出现在构造函数中来实现这一点(并且使得#34;重用"构造函数;无论何时创建新类型,都会创建新的)。

Haskell的类型系统的工作方式取决于缺少子类型。您可以设计一种允许子类型的语言(可能参见Scala)。但它从根本上说不是Haskell。

但你可以做的是定义类似的东西:

data Expr
  = ExprN N
  | ExprV V
  | ExprF Expr Expr

您仍然无法获得N值,只能将其用作Expr。但您可以将ExprN应用于它,然后您拥有Expr。而且,如果Haskell允许您使用nN作为Expr,那么它真的没有负担,但只需要添加类型注释澄清这就是你的意思;你只需说ExprN n而不是n :: Expr

同样地,如果您有Expr,并且想要在N上应用函数,那么case语句将从N构造函数中提取ExprN(如果那里的代码真的不再是你必须写的,以检查你的Expr是否真的是N

1 " 输入构造函数"是Haskell中的一个特定术语,这不是我们在这里谈论的内容。我非常确定你的意思是"类型的构造函数"但是要迂腐你通过使用该术语意外地引用了不同的东西。

要清除它,当您声明类似data Maybe a = Nothing | Just a的类型时,NothingJust是新的数据构造函数("构造函数&#34 ; on on on极可能意味着数据构造函数)而Maybe是一个新的类型构造函数