문제

OCaml's option type is really useful in cases where you have functions that might not return anything. But when I use this in many places, I find it cumbersome to handle the Some case and the None case all the time in a match ... with.

For example,

let env2 = List.map (fun ((it,ie),v,t) ->
  match t with
  | Some t -> (v,t)
  | None   ->
    begin
      match it with
      | Some it -> (v,it)
      | None    -> failwith "Cannot infer local vars"
    end) ls_res in

Are there any other ways to deconstruct the option type in a concise manner?

도움이 되었습니까?

해결책

For simple cases, you can match several things at once:

match t, it with
| Some t, _ -> (v, t)
| None, Some it -> (v, it)
| None, None -> failwith "Cannot infer local vars"

This is something I do all the time. I'm told the compiler is good with this construct (it doesn't actually generate an extra pair).

다른 팁

Depending on what you want to do, there are a variety of things you could write to help deal with these. For this pattern, I'd suggest writing something like the following:

let or_else opt1 opt2 = match opt1 with 
  | Some _ -> opt1
  | None -> opt2

And then restructuring your code as:

let env2 = List.map (fun ((it,ie),v,t) ->
  match (or_else opt1 opt2) with
  | Some t -> (v,t)
  | None   -> failwith "Cannot infer local vars") ls_res in

If you've got more than this number of options, then you can fold or_else over them in a list:

let a = [None; None; Some 1; Some 2;];;
List.fold a ~init:None ~f:or_else;;
  • The option monad (aka. maybe monad). Note that Just in Haskell is Some in OCaml and Nothing in Haskell is None in OCaml. http://en.wikipedia.org/wiki/Option_type#The_option_monad
  • Higher-order functions: default : 'a -> 'a option -> 'a, map_option : ('a -> 'b) -> 'a option -> 'b option, or_else as in another answer, map_some : ('a -> 'b option) -> 'a list -> 'b list, concat_some : 'a option list -> 'a list etc. My names might not be standard.
  • If you're in for a trouble, unsome : 'a option -> 'a, let unsome = function Some a -> a | None -> raise Not_found. Actually, this is useful if you have higher-order functions to deal with the pervasive Not_found exception.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top