Haskell 省略数据类型构造函数

Haskell 省略数据类型构造函数,haskell,types,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实现是: d

我试图在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中必须使用类型构造函数

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

语法在类型层面有缺陷吗?这有意义吗?所有术语看起来都像是类型检查(允许0,1,…同时为Expr和N子类型,x,y,…同时为Expr和V子类型)

Haskell中强制使用数据构造函数1的原因是为了确保不能将x、y……同时作为Expr和V子类型

因此,您的语法看起来是您希望语言术语如何工作的一个合理模型,但它对于您希望如何将语言术语表示为Haskell数据类型的直接设计毫无意义

基本上,Haskell故意没有子类型。它确保在创建新类型(使用
newtype
data
)时,新类型的所有值都不同于所有其他现有类型(以及将来将创建的所有类型)的值。它通过让用户定义类型的值始终出现在构造函数中来实现这一点(并且使得不可能“重用”构造函数;每当创建新类型时,您总是创建新的构造函数)

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

但你可以做的是定义如下:

data Expr
  = ExprN N
  | ExprV V
  | ExprF Expr Expr
你仍然不能有一个
N
值,只把它用作
Expr
。但是你可以把
ExprN
应用到它上面,然后你就有了一个
Expr
。如果Haskell允许你把
N
类型的
N
也用作
Expr
,但只需要你添加一个键入注释,说明这就是您的意思;您只需说
ExprN n
,而不是
n::Expr

类似地,当你有一个
Expr
并且你想对它应用一个
N
函数时,从
ExprN
构造函数中提取
N
的case语句(如果有)实际上没有比你需要写的更多的代码来检查你的
Expr
是否是一个
N


1“Typeconstructor”是Haskell中的一个特定术语,这不是我们在这里讨论的。我很确定你的意思是“类型的构造函数”,但学究式的说法是,你无意中使用了这个术语,指代了一件不同的事情


为了澄清这一点,当您声明像
data可能a=Nothing | Just a
这样的类型时,
Nothing
Just
都是新的数据构造函数(
上的构造函数极有可能表示数据构造函数)而且
可能是一个新的类型构造函数

这不是伪代码-它只是一个语法。另外,我不确定你所说的
MakeExpr:F->Expr->Expr->Expr->(Expr,Expr);MakeExpr fxy=(F,x,y)是什么意思
-
MakeExpr
已在
data Expr=N | V | MakeExpr F Expr Expr
中定义。此外,您可能希望在
N
V
变量中记录实际值。在任何情况下,我都不确定您在问什么。修复了,现在应该更有意义了。构造函数不能以
+
等符号开头ider
data F=Plus | Minus | dotdot
。但是,您可以使用中缀构造函数,如
data Foo=Int:+Char | String:*Bool