OCaml的Java保护类型类比

OCaml的Java保护类型类比,ocaml,Ocaml,你好,斯塔克 在Java实践中,存在一些关于部分定义函数的问题。有时,将错误处理与计算本身分离是很方便的。我们可以使用一种称为“防护类型”或“防护装饰器”的方法。 考虑一个简单的合成例子:保护空引用。这可以在下一节课的帮助下完成 public class NonNull<T> { public take() { return null != this.ref ? this.ref : throw new ExcptionOfMine("message");

你好,斯塔克

在Java实践中,存在一些关于部分定义函数的问题。有时,将错误处理与计算本身分离是很方便的。我们可以使用一种称为“防护类型”或“防护装饰器”的方法。 考虑一个简单的合成例子:保护空引用。这可以在下一节课的帮助下完成

public class NonNull<T> {
    public take() {
        return null != this.ref ? this.ref : throw new ExcptionOfMine("message");
    }

    public NotNull(T ref_) {
        this.ref     = ref_;
    }

    private T ref;       
}
公共类非空{
公众接受{
返回null!=this.ref?this.ref:抛出新的ExcptionOfMine(“消息”);
}
公共NotNull(T参考值){
this.ref=ref_u2;;
}
私人T参考;
}
问题是
有没有办法在OCaml中实现相同的“保护类型”,而不触及其对象模型?我相信作为函数式编程语言的OCaml应该拥有足够的抽象方法,而不需要面向对象的技术。

有一个可选类型的概念,您可以根据它进行有效的模式匹配。例如:

let optional = Some 20
let value = 
  match optional with
  | Some v -> v
  | None -> 0

您可以使用抽象类型来获得相同的效果。OCaml对空指针没有问题。因此,假设您希望以与上面相同的方式表示一个非空列表。也就是说,您希望能够创建空值,但仅当用户试图访问该值时才会抱怨

module G :
sig type 'a t 
    val make : 'a list -> 'a t 
    val take : 'a t -> 'a list 
end =
struct
    type 'a t = 'a list
    let make x = x
    let take x = if x = [] then raise (Invalid_argument "take") else x
end
以下是使用该模块时的外观:

$ ocaml
        OCaml version 4.02.1

# #use "m.ml";;
module G :
  sig type 'a t val make : 'a list -> 'a t val take : 'a t -> 'a list end
# let x = G.make [4];;
val x : int G.t = <abstr>
# G.take x;;
- : int list = [4]
# let y = G.make [];;
val y : '_a G.t = <abstr>
# G.take y;;
Exception: Invalid_argument "take".
$ocaml
OCaml版本4.02.1
##使用“m.ml”;;
模块G:
信号类型'a t val make:'a list->'a t val take:'a t->'a list end
#设x=G.make[4];;
val x:int G.t=
#G.取x;;
-:int list=[4]
#设y=G.make[];;
值y:'_ag.t=
#G.take y;;
异常:无效的_参数“take”。

您可以使用简单的闭包

let guard_list v =
  fun () ->
    if v = [] then failwith "Empty list"
    else v

let () =
  let a = guard_list [1;2;3] in
  let b = guard_list [] in
  print_int (List.length (a ()));  (* prints 3 *)
  print_int (List.length (b ()))   (* throws Failure "Empty list" *)
或惰性值

let guard_string v = lazy begin
  if v = "" then failwith "Empty string"
  else v
end

let () =
  let a = guard_string "Foo" in
  let b = guard_string "" in
  print_endline (Lazy.force a);  (* prints "Foo" *)
  print_endline (Lazy.force b)   (* throws Failure "Empty string" *)

这似乎正是我一直在寻找的答案!谢谢!我考虑过这样一种方法。但是,我想声明一个类型来保护函数参数,而不仅仅是lazy avaluate。使用抽象类型,可以定义这样的函数
let guarded_head g_lst=head(g.take g_lst)它被输入为
'a G.t->'a
现在我不必为
保护的头部中的空列表而烦恼了
G.take
负责错误处理。例如,可以声明G.take以返回
G.make
中指定的一些默认值,而不是立即失败。如果你有其他想法,那么你可以和我们分享。