Types 在类型级别将自定义类型定义为整数的子集

Types 在类型级别将自定义类型定义为整数的子集,types,ocaml,Types,Ocaml,我对在较大图像类型的层次结构中定义基本类型(颜色通道)感兴趣。由于所讨论的类型表示一个位,因此将其可能值限制为0到255范围内的整数似乎是合理的。但是,我不知道在类型级别实现这样的约束是否是OCaml的类型系统中通常要做的事情 type channel=int(*限制为范围0->255*) 如果这样做在OCaml类型系统中是合法的,那么应该如何在类型级别定义整数集的约束呢更具体地说,如何将类型定义为整数的子集(范围)?如果定义此类子类型,Ocaml将如何派生适用于此子类型的操作?(+,-,*,-

我对在较大图像类型的层次结构中定义基本类型(颜色通道)感兴趣。由于所讨论的类型表示一个位,因此将其可能值限制为0到255范围内的整数似乎是合理的。但是,我不知道在类型级别实现这样的约束是否是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 = ()