수색…


차별화 된 유니온 내의 튜플 요소 이름 지정

구분 된 공용체를 정의 할 때 튜플 유형의 요소를 명명하고 패턴 일치 중에이 이름을 사용할 수 있습니다.

type Shape = 
    | Circle of diameter:int
    | Rectangle of width:int * height:int

let shapeIsTenWide = function
    | Circle(diameter=10) 
    | Rectangle(width=10) -> true
    | _ -> false

또한 차별화 된 공용체의 요소 이름을 지정하면 코드의 가독성이 향상되고 C #과의 상호 운용성이 제공되므로 속성 이름 및 생성자 매개 변수에 제공된 이름이 사용됩니다. interop 코드의 기본 생성 이름은 "Item", "Item1", "Item2"...입니다.

차별 된 연합 사용법

F #의 차별화 된 노동 조합은 다양한 데이터 유형을 보유 할 수있는 유형을 정의 할 수있는 방법을 제공합니다. 이들의 기능은 C ++ 유니온 또는 VB 변형과 유사하지만 유형 안전성이라는 추가적인 이점이 있습니다.

// define a discriminated union that can hold either a float or a string
type numOrString = 
    | F of float
    | S of string

let str = S "hi" // use the S constructor to create a string
let fl = F 3.5 // use the F constructor to create a float

// you can use pattern matching to deconstruct each type
let whatType x = 
    match x with
        | F f -> printfn "%f is a float" f
        | S s -> printfn "%s is a string" s

whatType str // hi is a string
whatType fl // 3.500000 is a float

열거 형 조합

유형 정보는 차별 된 조합의 경우에 포함될 필요가 없습니다. 형식 정보를 생략하면 열거 형과 비슷한 선택 집합을 나타내는 유니온을 만들 수 있습니다.

// This union can represent any one day of the week but none of 
// them are tied to a specific underlying F# type
type DayOfWeek = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday

리플렉션으로 문자열 변환

Discriminated Union을 문자열로 변환하거나 문자열로 변환해야하는 경우가 있습니다.

module UnionConversion 
    open Microsoft.FSharp.Reflection
    
    let toString (x: 'a) = 
        match FSharpValue.GetUnionFields(x, typeof<'a>) with
        | case, _ -> case.Name

    let fromString<'a> (s : string) =
        match FSharpType.GetUnionCases typeof<'a> |> Array.filter (fun case -> case.Name = s) with 
        | [|case|] -> Some(FSharpValue.MakeUnion(case, [||])) :?> 'a)
        | _ -> None

단일 케이스 차별화 된 노동 조합

단일 케이스 차별화 된 노동 조합은 다른 차별화 된 노동 조합과 같지만 단지 하나의 케이스 만이 있습니다.

// Define single-case discriminated union type.
type OrderId = OrderId of int
// Construct OrderId type.
let order = OrderId 123
// Deconstruct using pattern matching. 
// Parentheses used so compiler doesn't think it is a function definition.   
let (OrderId id) = order

이는 형식 안전성을 강화하는 데 유용하며 새로운 유형을 만드는 데 더 많은 오버 헤드가있는 C # 및 Java와는 달리 F #에서 일반적으로 사용됩니다.

다음의 두 가지 대체 유형 정의는 동일한 단일 케이스 식별 조합이 선언되도록합니다.

type OrderId = | OrderId of int

type OrderId =
      | OrderId of int

단일 케이스 식별 유니온을 레코드로 사용하기

때로는 레코드와 같은 유형을 구현하기 위해 하나의 케이스 만 사용하여 공용체 유형을 만드는 것이 유용합니다.

type Point = Point of float * float

let point1 = Point(0.0, 3.0)

let point2 = Point(-2.5, -4.0)

이것들은 tuple 인수와 같은 방법으로 패턴 일치를 통해 분해 될 수 있기 때문에 매우 유용합니다 :

let (Point(x1, y1)) = point1
// val x1 : float = 0.0
// val y1 : float = 3.0

let distance (Point(x1,y1)) (Point(x2,y2)) =
    pown (x2-x1) 2 + pown (y2-y1) 2 |> sqrt
// val distance : Point -> Point -> float

distance point1 point2
// val it : float = 7.433034374

RequireQualifiedAccess

으로 RequireQualifiedAccess 속성, 노동 조합의 경우는 다음과 같이 언급해야 MyUnion.MyCase 대신의 MyCase . 이렇게하면 둘러싸는 네임 스페이스 또는 모듈에서 이름 충돌을 방지 할 수 있습니다.

type [<RequireQualifiedAccess>] Requirements =
    None | Single | All

// Uses the DU with qualified access
let noRequirements = Requirements.None

// Here, None still refers to the standard F# option case
let getNothing () = None

// Compiler error unless All has been defined elsewhere
let invalid = All

예를 들어 System 이 열린 경우 SingleSystem.Single 나타냅니다. 노조 케이스 Requirements.Single 과 충돌이 없습니다.

재귀 차별 노동 조합

재귀 유형

차별화 된 노동 조합은 반복적 일 수 있습니다. 즉, 자신이 정의한 것을 참조 할 수 있습니다. 여기서 가장 좋은 예는 나무입니다.

type Tree =
    | Branch of int * Tree list
    | Leaf of int

예를 들어 다음 트리를 정의 해 보겠습니다.

    1
  2   5
3   4

다음과 같이 재귀 적 차별화 된 유니온을 사용하여이 트리를 정의 할 수 있습니다.

let leaf1 = Leaf 3
let leaf2 = Leaf 4
let leaf3 = Leaf 5

let branch1 = Branch (2, [leaf1; leaf2])
let tip = Branch (1, [branch1; leaf3])

나무를 반복하는 것은 패턴 일치의 문제입니다.

let rec toList tree =
    match tree with
    | Leaf x -> [x]
    | Branch (x, xs) -> x :: (List.collect toList xs)

let treeAsList = toList tip // [1; 2; 3; 4; 5]

상호 종속적 재귀 유형

재귀를 달성하는 한 가지 방법은 상호 의존적 인 유형을 중첩하는 것입니다.

// BAD
type Arithmetic = {left: Expression; op:string; right: Expression}
// illegal because until this point, Expression is undefined
type Expression = 
| LiteralExpr of obj
| ArithmeticExpr of Arithmetic

차별화 된 공용체 내에서 레코드 유형을 직접 정의하는 것은 권장되지 않습니다.

// BAD
type Expression = 
| LiteralExpr of obj
| ArithmeticExpr of {left: Expression; op:string; right: Expression}
// illegal in recent F# versions

and 키워드를 사용하여 상호 종속 정의를 연결할 수 있습니다.

// GOOD
type Arithmetic = {left: Expression; op:string; right: Expression}
and Expression = 
| LiteralExpr of obj
| ArithmeticExpr of Arithmetic


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