具有相同构造函数名称的标准 ML 数据类型中的类型冲突
Type clash in Standard ML datatype with same constructor name
我需要在 Standard-ML 中描述一种由属性和值组成的语言。我的 属性 系统由可以具有值的属性组成,例如:
color: red | yellow | blue | transparent
align: left | center | right
bgcolor: red | yellow | blue | transparent
我创建了这个试图描述这些属性的 sml 文件:
datatype colorvalue = Transparent
| Yellow
| Blue
| Red
datatype bgcolorvalue = Transparent
| Yellow
| Blue
| Red
datatype alignvalue = Left
| Center
| Right
(* Generic property: it can be any of the above *)
datatype property = Color of colorvalue
| BgColor of bgcolorvalue
| Align of alignvalue
(* Some values *)
val prop1: property = Color Transparent
val prop2: property = BgColor Transparent
当我在 MoscowML 中编译时,我得到:
,File "c:\Users\myuser\documents\myproj\property.sml", line 21, characters 31-42:
! val prop1: property = Color Transparent
! ^^^^^^^^^^^
! Type clash: expression of type
! bgcolorvalue
! cannot have type
! colorvalue
我的猜测
所以我认为问题在于 color
和 bgcolor
共享一个共同的 属性 值:transparent
这反映在数据类型 colorvalue
和 bgcolorvalue
共享构造函数 Transparent
。实际上它们共享所有值,因此所有构造函数。
- 是这个失败的原因吗?
- 无论如何,我应该如何描述我的系统?
很容易看出,尝试在同一范围内的不同类型中使用相同的构造函数会产生类型推断问题。比如
的类型应该是什么
fun heat Transparent = Yellow
| heat Yellow = Red
| heat Red = Blue
| heat Blue = Blue;
是吗? colorvalue ->colorvalue
或 bgbcolorvalue -> bgbcolorvalue
或 colorvalue -> bgbcolorvalue
或 bgbcolorvalue -> colorvalue
?
最简单的解决方法是对构造函数采用不同的命名约定。您还可以使用结构(这就是 SML 如何在基础库中保持名称 map
的不同用法而没有任何冲突)。类似于:
structure Color = struct
datatype value = Transparent
| Yellow
| Blue
| Red
end
structure BGBColor = struct
datatype value = Transparent
| Yellow
| Blue
| Red
end;
然后您可以执行以下操作:
- val a = Color.Transparent;
val a = Transparent : Color.value
- val b = BGBColor.Transparent;
val b = Transparent : BGBColor.value
最后一个是 运行 在 SML/NJ REPL 中,说明现在没有冲突。
我需要在 Standard-ML 中描述一种由属性和值组成的语言。我的 属性 系统由可以具有值的属性组成,例如:
color: red | yellow | blue | transparent
align: left | center | right
bgcolor: red | yellow | blue | transparent
我创建了这个试图描述这些属性的 sml 文件:
datatype colorvalue = Transparent
| Yellow
| Blue
| Red
datatype bgcolorvalue = Transparent
| Yellow
| Blue
| Red
datatype alignvalue = Left
| Center
| Right
(* Generic property: it can be any of the above *)
datatype property = Color of colorvalue
| BgColor of bgcolorvalue
| Align of alignvalue
(* Some values *)
val prop1: property = Color Transparent
val prop2: property = BgColor Transparent
当我在 MoscowML 中编译时,我得到:
,File "c:\Users\myuser\documents\myproj\property.sml", line 21, characters 31-42:
! val prop1: property = Color Transparent
! ^^^^^^^^^^^
! Type clash: expression of type
! bgcolorvalue
! cannot have type
! colorvalue
我的猜测
所以我认为问题在于 color
和 bgcolor
共享一个共同的 属性 值:transparent
这反映在数据类型 colorvalue
和 bgcolorvalue
共享构造函数 Transparent
。实际上它们共享所有值,因此所有构造函数。
- 是这个失败的原因吗?
- 无论如何,我应该如何描述我的系统?
很容易看出,尝试在同一范围内的不同类型中使用相同的构造函数会产生类型推断问题。比如
的类型应该是什么fun heat Transparent = Yellow
| heat Yellow = Red
| heat Red = Blue
| heat Blue = Blue;
是吗? colorvalue ->colorvalue
或 bgbcolorvalue -> bgbcolorvalue
或 colorvalue -> bgbcolorvalue
或 bgbcolorvalue -> colorvalue
?
最简单的解决方法是对构造函数采用不同的命名约定。您还可以使用结构(这就是 SML 如何在基础库中保持名称 map
的不同用法而没有任何冲突)。类似于:
structure Color = struct
datatype value = Transparent
| Yellow
| Blue
| Red
end
structure BGBColor = struct
datatype value = Transparent
| Yellow
| Blue
| Red
end;
然后您可以执行以下操作:
- val a = Color.Transparent;
val a = Transparent : Color.value
- val b = BGBColor.Transparent;
val b = Transparent : BGBColor.value
最后一个是 运行 在 SML/NJ REPL 中,说明现在没有冲突。