使用 ADT 和(可能)GADT 在类型系统中表达层次结构
Expressing a hierarchy within a type-system with ADT and (possibly) GADT
在我的类型系统中,我想支持可升级类型,其中 Int
如果与除法一起使用,将升级为 Double
,而 String
将升级为 StringBuffer
如果与串联一起使用。我可以用 agebraic 数据类型来表达它吗,这样如果编译器试图提升错误的类型,它就会抛出一个类型错误?
例如:
type ty =
| Int
| Double
| String
| StringBuffer
| Promotable of ref ty
但是,Int
只能提升到Double
,不能提升到StringBuffer
或String
.
使用 GADT:
type _ ty =
| Int : arith ty
| Double : arith ty
| String : text ty
| StringBuffer : text ty
| Promotable of ref ty : ... ??
其中arith
和text
需要是类型"family"(种类,类型class)?我可以用 OCaml 表达吗?
提前致谢!
编辑:基于以下答案的示例用法:
let promote : type a. a ty -> a ty = function
| Promotable (Int, IntToDouble) ->Double (* StringBuffer here would not type-check *)
| Promotable (String, StringToStringBuffer) -> StringBuffer
| t -> t
您可以有另一个 GADT 来描述层次结构是什么,然后期望当有人试图提升价值时向您提供证明。例如:
type arith
type text
type (_ , _) lessThan =
| IntToDouble : (arith, arith) lessThan
| StringToStringBuffer : (text, text) lessThan
type _ ty =
| Int : arith ty
| Double : arith ty
| String : text ty
| StringBuffer : text ty
| Promotable : 'ref ty * ('ref, 'promo) lessThan -> 'promo ty
在我的类型系统中,我想支持可升级类型,其中 Int
如果与除法一起使用,将升级为 Double
,而 String
将升级为 StringBuffer
如果与串联一起使用。我可以用 agebraic 数据类型来表达它吗,这样如果编译器试图提升错误的类型,它就会抛出一个类型错误?
例如:
type ty =
| Int
| Double
| String
| StringBuffer
| Promotable of ref ty
但是,Int
只能提升到Double
,不能提升到StringBuffer
或String
.
使用 GADT:
type _ ty =
| Int : arith ty
| Double : arith ty
| String : text ty
| StringBuffer : text ty
| Promotable of ref ty : ... ??
其中arith
和text
需要是类型"family"(种类,类型class)?我可以用 OCaml 表达吗?
提前致谢!
编辑:基于以下答案的示例用法:
let promote : type a. a ty -> a ty = function
| Promotable (Int, IntToDouble) ->Double (* StringBuffer here would not type-check *)
| Promotable (String, StringToStringBuffer) -> StringBuffer
| t -> t
您可以有另一个 GADT 来描述层次结构是什么,然后期望当有人试图提升价值时向您提供证明。例如:
type arith
type text
type (_ , _) lessThan =
| IntToDouble : (arith, arith) lessThan
| StringToStringBuffer : (text, text) lessThan
type _ ty =
| Int : arith ty
| Double : arith ty
| String : text ty
| StringBuffer : text ty
| Promotable : 'ref ty * ('ref, 'promo) lessThan -> 'promo ty