Udostępnij za pośrednictwem


Związki dyskryminowanych (F#)

Izolowanie związków zapewniają obsługę wartości, które może być jedną liczbę przypadków, prawdopodobnie każdy z różnych wartości i typy.Związki dyskryminowanych są przydatne w przypadku heterogenicznych danych; dane, które mogą mieć specjalnych przypadków, w tym ważny i w przypadku wystąpienia błędów; dane, które zależy od typu z jednego wystąpienia do innego; i jako alternatywa dla małych obiektu w hierarchii.Ponadto izolowanie rekurencyjne związki są używane do reprezentowania drzewo struktury danych.

type type-name =
   | case-identifier1 [of type1 [ * type2 ...]
   | case-identifier2 [of type3 [ * type4 ...]
   ...

Uwagi

Związki dyskryminowanych są podobne do typów Unii w innych językach, ale występują różnice.Jako typu Unii w języku C++ lub typ wariantu języka Visual Basic, dane przechowywane w wartości nie jest ustalona; może być jedną z kilku opcji distinct.W przeciwieństwie do związków w tych innych języków, jednak każdy z możliwych opcji znajduje się identyfikator przypadku.Sprawa identyfikatory są nazwy dla różnych rodzajów wartości, które mogą zawierać obiekty tego typu; wartości są opcjonalne.Jeśli wartości nie są obecne, sprawy jest równoznaczne z wyliczenia dla każdego przypadku.Jeśli wartości są obecne, każda wartość może być pojedynczą wartość określonego typu lub spoiny, który agreguje wartości wielu z tych samych lub różnych typów.

option Typu jest proste Unii dyskryminowanych w bibliotece core F#.option Typ został zadeklarowany w następujący sposób.

// The option type is a discriminated union.
type Option<'a> =
    | Some of 'a
    | None

Poprzedni kod określa, że typ Option jest dyskryminowanych Unii, który ma dwa przypadki, Some i None.Some Przypadku ma skojarzonej wartości, których typ jest reprezentowana przez parametr typu 'a.None Przypadku nie ma skojarzonej wartości.Zatem option type określa typ rodzajowy, który ma wartość pewien typ lub wartość nie.Typ Option ma również alias typu małymi literami, option, to znaczy więcej powszechnie stosowane.

Identyfikatory sprawa może służyć jako konstruktory dyskryminowanych typu Unii.Na przykład, poniższy kod jest używany do tworzenia wartości option typu.

let myOption1 = Some(10.0)
let myOption2 = Some("string")
let myOption3 = None

Sprawa identyfikatory są również używane w wyrażeniach dopasowania do wzorca.Identyfikatory w wyrażenie dopasowania do wzorca, przewidziane są wartości skojarzone z indywidualnych przypadkach.Na przykład w poniższym kodzie x jest identyfikatorem podane wartości, który jest skojarzony z Some w przypadku option typu.

let printValue opt =
    match opt with
    | Some x -> printfn "%A" x
    | None -> printfn "No value."

Normalnie identyfikatory sprawa może być używany bez kwalifikującą je o nazwie Unii.Jeśli chcesz, aby nazwa, aby zawsze kwalifikowaną nazwą Unii, można zastosować RequireQualifiedAccess atrybut do definicji typu Unii.

Używanie dyskryminowanych związków hierarchie obiektu

Prostsze alternatywne w stosunku do hierarchii małych obiektów, można często używają dyskryminowanych Unii.Na przykład, następujące dyskryminowanych Unii może wykorzystać zamiast Shape base klasy, która przygotowała typów dla okręgu, kwadratowa, i tak dalej.

type Shape =
  // The value here is the radius.
| Circle of float
  // The value here is the side length.
| EquilateralTriangle of double
  // The value here is the side length.
| Square of double
  // The values here are the height and width.
| Rectangle of double * double

Zamiast wirtualnego metody do obliczenia powierzchni lub obwód, jak mogłaby być używana w implementacja zorientowane obiektowo, można użyć wzorzec dopasowania do gałęzi do odpowiednich formuły do obliczania tych ilości.W poniższym przykładzie różne formuły są używane do obliczania powierzchni, w zależności od kształtu.

let pi = 3.141592654

let area myShape =
    match myShape with
    | Circle radius -> pi * radius * radius
    | EquilateralTriangle s -> (sqrt 3.0) / 4.0 * s * s
    | Square s -> s * s
    | Rectangle (h, w) -> h * w

let radius = 15.0
let myCircle = Circle(radius)
printfn "Area of circle that has radius %f: %f" radius (area myCircle)

let squareSide = 10.0
let mySquare = Square(squareSide)
printfn "Area of square that has side %f: %f" squareSide (area mySquare)

let height, width = 5.0, 10.0
let myRectangle = Rectangle(height, width)
printfn "Area of rectangle that has height %f and width %f is %f" height width (area myRectangle)

Produkcja jest w następujący sposób:

Area of circle that has radius 15.000000: 706.858347
Area of square that has side 10.000000: 100.000000
Area of rectangle that has height 5.000000 and width 10.000000 is 50.000000

Za pomocą dyskryminowanych związków dla struktur drzewa danych

Związki dyskryminowanych może być rekursywne, co oznacza, że samej Unii mogą być ujęte w typu jeden lub więcej przypadków.Cykliczne dyskryminowanych związków może służyć do tworzenia struktury drzewa, które są używane do modelu wyrażeń w językach programowania.W poniższym kodzie izolowanie cyklicznej Unii jest używany do tworzenia struktury danych binarnych drzewa.Unii składa się z dwóch przypadkach, Node, który jest węzeł z wartością całkowitą i poddrzew lewe i prawe i Tip, który kończy drzewa.

type Tree =
    | Tip
    | Node of int * Tree * Tree

let rec sumTree tree =
    match tree with
    | Tip -> 0
    | Node(value, left, right) ->
        value + sumTree(left) + sumTree(right)
let myTree = Node(0, Node(1, Node(2, Tip, Tip), Node(3, Tip, Tip)), Node(4, Tip, Tip))
let resultSumTree = sumTree myTree

W poprzednim kodzie resultSumTree ma wartość 10.Na następującej ilustracji pokazano strukturę drzewa myTree.

Struktura drzewa myTree

Diagram drzewa dla związków dyskryminowane

Związki dyskryminowanych działają dobrze w przypadku heterogenicznych węzłów w drzewie.W poniższym kodzie typu Expression reprezentuje drzewo składni abstrakcyjnej wyrażenia w prosty język programowania, który obsługuje dodawanie i mnożenie liczb i zmiennych.Niektóre przypadki Unii nie są cykliczne i reprezentują albo liczb (Number) lub zmiennych (Variable).Inne przypadki są cykliczne i reprezentują operacji (Add i Multiply), gdzie operandy są również wyrażenia.Evaluate Funkcja używa wyrażenie dopasowania do procesu rekursywnie drzewo składni.

type Expression = 
    | Number of int
    | Add of Expression * Expression
    | Multiply of Expression * Expression
    | Variable of string

let rec Evaluate (env:Map<string,int>) exp = 
    match exp with
    | Number n -> n
    | Add (x, y) -> Evaluate env x + Evaluate env y
    | Multiply (x, y) -> Evaluate env x * Evaluate env y
    | Variable id    -> env.[id]

let environment = Map.ofList [ "a", 1 ;
                               "b", 2 ;
                               "c", 3 ]

// Create an expression tree that represents
// the expression: a + 2 * b.
let expressionTree1 = Add(Variable "a", Multiply(Number 2, Variable "b"))

// Evaluate the expression a + 2 * b, given the
// table of values for the variables.
let result = Evaluate environment expressionTree1

Kiedy ten kod jest wykonywany, wartość result jest 5.

Zobacz też

Inne zasoby

F# Language Reference