Types 在类型级别将自定义类型定义为整数的子集
我对在较大图像类型的层次结构中定义基本类型(颜色通道)感兴趣。由于所讨论的类型表示一个位,因此将其可能值限制为0到255范围内的整数似乎是合理的。但是,我不知道在类型级别实现这样的约束是否是OCaml的类型系统中通常要做的事情Types 在类型级别将自定义类型定义为整数的子集,types,ocaml,Types,Ocaml,我对在较大图像类型的层次结构中定义基本类型(颜色通道)感兴趣。由于所讨论的类型表示一个位,因此将其可能值限制为0到255范围内的整数似乎是合理的。但是,我不知道在类型级别实现这样的约束是否是OCaml的类型系统中通常要做的事情 type channel=int(*限制为范围0->255*) 如果这样做在OCaml类型系统中是合法的,那么应该如何在类型级别定义整数集的约束呢更具体地说,如何将类型定义为整数的子集(范围)?如果定义此类子类型,Ocaml将如何派生适用于此子类型的操作?(+,-,*,-
type channel=int(*限制为范围0->255*)
如果这样做在OCaml类型系统中是合法的,那么应该如何在类型级别定义整数集的约束呢更具体地说,如何将类型定义为整数的子集(范围)?如果定义此类子类型,Ocaml将如何派生适用于此子类型的操作?(+,-,*,-). 初始类型与其子类型之间的操作是什么 除了Ocaml中的对象之外,没有办法通过缩小另一种类型的定义来定义约束类型
在您的情况下,
通道
应映射到字符
类型-但仍需定义实现算术所需的所有操作。另一种解决方案是定义具有私有类型的模块,如下所示:
module type INTERVAL = sig
type t = private int
val of_int : int -> t (* fails if value outside bounds *)
end
let interval a b = (module struct
type t = int
let of_int v =
if v < a || v > b
then failwith (Printf.sprintf "Not in interval [%d, %d]" a b)
else v
end : INTERVAL)
以这种方式构建的模块允许您使用一组受限的整数值。但是,它们有几个缺点:
- 必须先将值转换回整数,然后才能对其使用运算符(使用:>运算符,如示例所示)李>
- 类型本身不提供任何关于允许的实际边界的信息;为了了解类型的含义,您必须查看实现或阅读文档李>
- 使用的内存空间是一个整数,在这种情况下不是一个字节李>
- 如果实例化具有相同边界的两个模块,则它们的类型t将不兼容
module type INTERVAL = sig
type t = private int
val of_int : int -> t
val ( + ) : t -> t -> t
val print_int : t -> unit
end
let interval a b = (module struct
type t = int
let of_int v =
if v < a || v > b
then failwith "Not in interval"
else v
let ( + ) x y = of_int (x + y)
let print_int x = print_int x
end : INTERVAL)
let () =
let module Small_int = (val (interval 0 255) : INTERVAL) in
let x = Small_int.of_int (read_int ()) in
let y = Small_int.of_int (read_int ()) in
Small_int.(print_int (x + y));
print_newline ()
模块类型间隔=sig
类型t=专用int
_int:int->t的值
val(+):t->t->t
val print_int:t->unit
结束
设区间a b=(模块结构
类型t=int
让我们来看看=
如果vb
然后使用“不在间隔内”进行故障诊断
其他五
设(+)x y=整数(x+y)
让print_int x=print_int x
完:间隔时间)
让()=
让模块Small_int=(val(区间0 255):区间)在
设x=in中的小整数(read)
设y=in中的小整数
小整数(打印整数(x+y));
打印新行()
第二个缺点可以通过在项目文档中声明的一些约定来克服
当您希望确保给定给函数的输入在某个“合法”范围内时,这有时很有用。如果您是OCaml新手,我不确定您是否想使用它,但知道它可以实现还是很有用的。也许您可以使用函子:
module type Elt_type =
sig
type t
val min : t
val max : t
val (<) : t -> t -> bool
val (>) : t -> t -> bool
val (+) : t -> t -> t
val print : t -> unit
end
module Make (Elt : Elt_type) =
struct
type t' = Set of Elt.t
let of_t x =
if Elt.(<) x Elt.min || Elt.(>) x Elt.max
then failwith "Not in interval"
else Set x
let to_t x' = let Set x=x' in x
let (+) x' y'= of_t (Elt.(+) (to_t x') (to_t y'))
let print x' = Elt.print (to_t x')
end
module Int =Make (
struct
type t = int
let min = 1
let max = 10
let (<) = Pervasives.(<)
let (>) = Pervasives.(>)
let (+) = Pervasives.(+)
let print = Pervasives.print_int
end)
将
频道
映射到字符
是一个极好的解决方案。当在像算术这样简单的操作中维护这样的约束让人头疼时,类型不能像我建议的那样受到约束是有道理的。不过,我不想在没有充分理由的情况下排除这种可能性。通过这种方式,您甚至可以强制执行希望得到的算法:或者+可以触发异常,或者执行一些模块化算术。
module type Elt_type =
sig
type t
val min : t
val max : t
val (<) : t -> t -> bool
val (>) : t -> t -> bool
val (+) : t -> t -> t
val print : t -> unit
end
module Make (Elt : Elt_type) =
struct
type t' = Set of Elt.t
let of_t x =
if Elt.(<) x Elt.min || Elt.(>) x Elt.max
then failwith "Not in interval"
else Set x
let to_t x' = let Set x=x' in x
let (+) x' y'= of_t (Elt.(+) (to_t x') (to_t y'))
let print x' = Elt.print (to_t x')
end
module Int =Make (
struct
type t = int
let min = 1
let max = 10
let (<) = Pervasives.(<)
let (>) = Pervasives.(>)
let (+) = Pervasives.(+)
let print = Pervasives.print_int
end)
# open Int
# let x = of_t 2;;
val x : Int.t' = Set 2
# let y = of_t 3;;
val y : Int.t' = Set 3
# print (x + y);;
5- : unit = ()