수색…
차별화 된 유니온 내의 튜플 요소 이름 지정
구분 된 공용체를 정의 할 때 튜플 유형의 요소를 명명하고 패턴 일치 중에이 이름을 사용할 수 있습니다.
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
이 열린 경우 Single
은 System.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