Generics 此构造导致代码不太通用。。。当应用于幻影类型时

Generics 此构造导致代码不太通用。。。当应用于幻影类型时,generics,f#,Generics,F#,我正在尝试用F#实现一种小型语言的DSL。不幸的是,当我试图约束节点以保存额外的类型信息(通过幻象类型)时,编译器会阻止我 以下代码行说明了该问题: type Expr<'a> = | Int of int | Eq of Expr<int> * Expr<int> | Not of Expr<bool> let rec to_string (expr: Expr<'a>) = match expr with | Int(

我正在尝试用F#实现一种小型语言的DSL。不幸的是,当我试图约束节点以保存额外的类型信息(通过幻象类型)时,编译器会阻止我

以下代码行说明了该问题:

type Expr<'a> =
| Int of int
| Eq  of Expr<int> * Expr<int>
| Not of Expr<bool>

let rec to_string (expr: Expr<'a>) = 
  match expr with
  | Int(n)   -> string n
  | Eq(x, y) -> sprintf "%s == %s" (to_string x) (to_string y)
  | Not(b)   -> sprintf "!%s" (to_string b)
type Expr)=
匹配表达式
|Int(n)->字符串n
|等式(x,y)->sprintf“%s==%s”(到字符串x)(到字符串y)
|非(b)->sprintf“!%s”(到字符串b)
根据编译器,构造
到字符串x
发出以下警告:

构造导致代码不像类型注释所指示的那样通用。类型变量“a”已被约束为类型“int”

接下来,在下一行,构造
到字符串b
发出此错误:

类型不匹配。应为
Expr
但给定
Expr
类型
int
与类型
bool

我似乎找不到任何方法来规避这种行为,事实上,我也找不到导致这段代码没有我预期的那么通用的原因。如果可能的话,我更喜欢不完全放弃幻影类型的解决方案


我是不是做错了什么?这可能是编译器错误吗?

您需要将
to_string
函数设置为通用函数:

let rec to_string<'a> (expr:Expr<'a>) : string = 
  match expr with
  | Int(n)   -> string n
  | Eq(x, y) -> sprintf "%s == %s" (to_string x) (to_string y)
  | Not(b)   -> sprintf "!%s" (to_string b)
Not (Eq (Int 1, Int 2))
|> to_string