수색…


옵션의 정의

Option 은 차별화 된 노조이며 None 또는 Some 두 가지 경우가 있습니다.

type Option<'T> = Some of 'T | None

Null 값에 대해 Option < 'T> 사용

F# 과 같은 함수형 프로그래밍 언어에서는 null 값이 잠재적으로 위험하고 가난한 스타일 (비 관용적)으로 간주됩니다.

C# 코드를 살펴 보겠습니다.

string x = SomeFunction ();
int    l = x.Length;

xnull 이면 x.Length 가 throw됩니다. 보호를 추가합니다.

string x = SomeFunction ();
int    l = x != null ? x.Length : 0;

또는:

string x = SomeFunction () ?? "";
int    l = x.Length;

또는:

string x = SomeFunction ();
int    l = x?.Length;

관용적 인 F# 에서는 null 값을 사용하지 않으므로 코드는 다음과 같습니다.

let x = SomeFunction ()
let l = x.Length

그러나 때로는 빈 값이나 유효하지 않은 값을 나타낼 필요가 있습니다. 그런 다음 Option<'T> 사용할 수 있습니다.

let SomeFunction () : string option = ...

SomeFunctionSome string 값 또는 None 반환합니다. 패턴 매칭을 사용하여 string 값을 추출합니다.

let v =
  match SomeFunction () with
  | Some x  -> x.Length
  | None    -> 0

이 코드가 다음보다 취약하지 않은 이유 :

string x = SomeFunction ();
int    l = x.Length;

string option 에서 Length 를 호출 할 수 없기 때문입니다. 우리는 추출 할 필요가 string 패턴 매칭을 사용하여 값을하고 그렇게함으로써 우리는 보장되는 string 값을 사용하는 것이 안전합니다.

옵션 모듈을 통해 철도 방향 프로그래밍 가능

오류 처리는 중요하지만 엉망으로 우아한 알고리즘을 만들 수 있습니다. ROP ( Railway Oriented Programming )는 오류 처리를 우아하고 구성 가능하게 만드는 데 사용됩니다.

간단한 함수 f 생각해보십시오.

let tryParse s =
  let b, v = System.Int32.TryParse s
  if b then Some v else None

let f (g : string option) : float option =
  match g with
  | None    -> None
  | Some s  ->
    match tryParse s with           // Parses string to int
    | None              -> None
    | Some v when v < 0 -> None     // Checks that int is greater than 0
    | Some v -> v |> float |> Some  // Maps int to float

f 의 목적은 입력 string 값 ( Some 가있는 경우)을 int 로 구문 분석하는 것입니다. int0 보다 큰 경우, float 캐스트합니다. 다른 모든 경우에 우리는 None 구제합니다.

중첩 된 match 기능은 매우 간단한 기능이지만 가독성을 크게 떨어 뜨립니다.

ROP 는 프로그램에서 두 가지 종류의 실행 경로가 있음을 확인합니다.

  1. 해피 경로 - 결국 계산됩니다 Some
  2. 오류 경로 - 다른 모든 경로 생성 None

오류 경로가 더 자주 발생하기 때문에 코드를 인계하는 경향이 있습니다. 행복한 패스 코드가 가장 눈에 띄는 코드 경로라고 생각합니다.

ROP 사용하는 동등한 함수 g 는 다음과 같습니다.

let g (v : string option) : float option =
  v
  |> Option.bind    tryParse  // Parses string to int
  |> Option.filter  ((<) 0)   // Checks that int is greater than 0
  |> Option.map     float     // Maps int to float

F# 에서 목록과 시퀀스를 처리하는 경향이 매우 비슷합니다.

하나는 볼 수있는 Option<'T> 유사한 List<'T> 만을 포함 할 수 0 또는 1 곳 요소를 Option.bind 처럼 동작 List.pick (개념적으로 Option.bind 에게 더 나은지도 List.collect 하지만 List.pick 수 있습니다 이해하기 쉽다).

bind , filtermap 은 오류 경로를 처리하고 g 는 해피 경로 코드 만 포함합니다.

직접 받아 모든 기능 Option<_> 반환합니다 Option<_> 직접 작성 가능하다 |>>> .

따라서 ROP 는 가독성과 조합 가능성을 높입니다.

C #의 옵션 유형 사용

C #에는 옵션 유형을 처리 할 수있는 방법이 없기 때문에 Option 유형을 C # 코드에 표시하는 것은 좋지 않습니다. 옵션은 FSharp.Core 를 C # 프로젝트 (C #으로 interop 용으로 설계 되지 않은 F # 라이브러리를 사용하는 경우 수행 FSharp.Core )에서 종속성으로 도입하거나 None 값을 null 로 변경하는 것입니다.

Pre-F # 4.0

이렇게하는 방법은 자신의 변환 함수를 만드는 것입니다.

let OptionToObject opt =
    match opt with
    | Some x -> x 
    | None -> null

값 유형의 경우 boxing하거나 System.Nullable 을 사용해야합니다.

let OptionToNullable x = 
    match x with 
    | Some i -> System.Nullable i
    | None -> System.Nullable ()

F # 4.0

F # 4.0에서 ofObj , toObj , ofNullabletoNullable 의 함수는 Option 모듈에 도입되었습니다. F # 대화식에서는 다음과 같이 사용할 수 있습니다.

let l1 = [ Some 1 ; None ; Some 2]
let l2 = l1 |> List.map Option.toNullable;;

// val l1 : int option list = [Some 1; null; Some 2]
// val l2 : System.Nullable<int> list = [1; null; 2]

let l3 = l2 |> List.map Option.ofNullable;;
// val l3 : int option list = [Some 1; null; Some 2]

// Equality
l1 = l2 // fails to compile: different types
l1 = l3 // true

None 내부적으로 null 컴파일됩니다. 그러나 F #에 관한 한 그것은 None 입니다.

let lA = [Some "a"; None; Some "b"]
let lB = lA |> List.map Option.toObj

// val lA : string option list = [Some "a"; null; Some "b"]
// val lB : string list = ["a"; null; "b"]

let lC = lB |> List.map Option.ofObj
// val lC : string option list = [Some "a"; null; Some "b"]

// Equality
lA = lB // fails to compile: different types
lA = lC // true


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow