我对在较大图像类型的层次结构中定义基元类型(颜色通道)感兴趣。由于所讨论的类型表示一点,将其可能值限制为仅0到255范围内的整数似乎是明智的。但是,我不知道在类型级别实现这些约束是否通常在OCaml的类型系统中完成。
type channel = int (* restrict to range 0 -> 255 *)
如果在OCaml类型系统中这样做是合法的,那么应该如何在类型级别定义对整数集的约束? 更具体地说,如何将类型定义为整数的子集(范围)?
答案 0 :(得分:4)
另一种解决方案是定义具有私有类型的模块,如下所示:
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)
使用示例:
let () =
let module Small_int = (val (interval 0 255) : INTERVAL) in
let x = Small_int.of_int (read_int ()) in
print_int ((x :> int) * 2)
以这种方式构建的模块允许您使用一组受限制的整数值。但是它们有几个缺点:
关于第一个缺点,没有任何限制您将操作添加到模块类型:
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 ()
使用您在项目文档中声明的一些约定可以克服第二个缺点。
当您想要确保给予函数的输入处于某个“合法”范围时,这有时很有用。如果您是OCaml的新手,我不确定您是否想要使用它,但是知道它可以完成它仍然很有用。
答案 1 :(得分:1)
如果您定义了这样的子类型,Ocaml将如何派生适用于此子类型的操作? (+, - ,*, - )。以及初始类型与其子类型之间的操作?
除Ocaml中的对象外,无法通过缩小其他类型的定义来定义约束类型。
在您的情况下,channel
应映射到char
类型 - 但它仍然是定义实现算术所需的所有操作。
答案 2 :(得分:1)
也许你可以使用Functor:
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 = ()