2013-02-20 2 views
4

OCaml의 옵션 유형은 아무 것도 반환하지 않는 함수가있는 경우에 유용합니다. 그러나 이것을 여러 곳에서 사용할 때, 케이스와 None 케이스를 항상 match ... with으로 처리하는 것이 번거로울 수 있습니다.OCaml에서 옵션 유형을 해체하는 다른 방법이 있습니까?

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 

은 간결한 방식으로 옵션 유형을 해체하는 다른 방법은 예를 들어

,이 있습니까?

답변

9

, 한 번에 여러 가지를 일치시킬 수 있습니다 :

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

이것은 내가 항상하는 일입니다. 컴파일러가이 구문을 잘 사용한다고 (실제로 추가 쌍을 생성하지는 않는다) 말했습니다.

+1

+1 나는 컴파일러가이 구조를 잘 사용한다고 들었지만 언젠가 나는 어셈블리를 보았다. (나는 람다 코드를 살펴볼 수 있었지만 이미 하나의 어셈블리 언어를 알고 있었기 때문에 실제로 나에게 덜 효과적이었다.) 나는 실망했다. 인상적인 최적화는 잊어 버린 명백한 경우처럼 보이게됩니다. 현재로서는 'caml_alloc2'에 대한 두 번의 호출이 없어야합니다. (하지만) http://pastebin.com/EfFsxhCQ –

+0

간단합니다. –

+0

감사합니다. 이것은 가장 간결하고 읽기 쉬운 대답입니다. –

1

당신이하고 싶은 것에 따라, 이것들을 다루기 위해 쓸 수있는 다양한 것들이 있습니다. 당신이 할 수있는,

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 

당신이 옵션의 수보다 더 가지고있는 경우에 :

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

을 그리고 다음과 같이 코드를 구조 조정이 패턴에 대해 나는 다음과 같은 일을 쓰는 게 좋을 것 목록에서 그들을 or_else 배 : 간단한 경우를 들어

let a = [None; None; Some 1; Some 2;];; 
List.fold a ~init:None ~f:or_else;; 
+0

감사합니다! 그러나 이것이 관용적 인 ocaml인지 확실하지 않습니다. :/ –

+0

아마도 그것이 가능하지 않을 수도 있지만, 나는 그 이유를 알 수 없습니다. Jane Street의 핵심 라이브러리는 자신의'Option' 클래스에서'first_some'으로 정의하므로'or_else'가 더 명확하지만 표준 라이브러리에 있습니다. – Impredicative

0
  • 옵션 모나드 (일명 모나드 일 수도 있음). 하스켈에서 Just은 OCaml에서 Some이고 하스켈에서는 Nothing이 OCaml에서 None 인 점에 유의하십시오. http://en.wikipedia.org/wiki/Option_type#The_option_monad
  • 고차 기능 : default : 'a -> 'a option -> 'a, map_option : ('a -> 'b) -> 'a option -> 'b option, 다른 답변에서와 같이 or_else, map_some : ('a -> 'b option) -> 'a list -> 'b list, concat_some : 'a option list -> 'a list 내 이름은 표준되지 않을 수도 등.
  • 문제가있는 경우 unsome : 'a option -> 'a, let unsome = function Some a -> a | None -> raise Not_found입니다. 실제로 이것은 광범위한 Not_found 예외를 처리하는 고차 함수가있는 경우 유용합니다.