Uniões discriminadas em F#

Uma União Discriminada (DU) é um recurso fornecido pelo F# que permite definir tipos aos quais podem ser atribuídos um conjunto fixo de valores, cada um dos quais pode ter diferentes tipos de dados associados a ele.

Existem muitos usos de DU, incluindo a modelagem de estruturas de dados complexas de maneira concisa e expressiva.

Ao longo deste artigo, veremos o que são uniões discriminadas , como são definidas e alguns exemplos de como utilizá-las em um projeto F#.

Sintaxe

A seguinte sintaxe pode ser usada para definir uniões discriminatórias:

type type-name =
| case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ]
type2 ...]
| case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]
...

Como exemplo de como podemos implementar “escolha” com uma abordagem simples, podemos descrevê-la da seguinte forma:

type choice =
| Yes
| No

Este exemplo ilustra o uso da escolha de tipo da seguinte maneira:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
type choice =
| Yes
| No
let a = Yes //create an instance of choice
let b = No //create another instance of choice
let main() =
printfn "a: %A" a
printfn "b: %A" b
main()
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

A seguinte saída será produzida como resultado:

Sindicatos Discriminados



Estado de tensão no tipo de escolha

Como exemplo, vamos dar uma olhada nos estados de tensão que definem um bit como alto ou baixo usando o seguinte código:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type VoltageState =
| High
| Low
let Switch = function
| High -> Low
| Low -> High
let main() =
let on = High
let off = Low
let change = Switch off
printfn "Switch on: %A" on
printfn "Switch off: %A" off
printfn "Toggle off: %A" change
printfn "Toggle Changed state: %A" (Switch change)
main()
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Saída de Sindicatos Discriminados


Área da forma usando o tipo de escolha

Usando o tipo de escolha abaixo, há um exemplo de cálculo da área de um quadrado, círculo e retângulo :

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type Shape =
| Circle of float
| Square of float
| Rectangle of float * float
let pi = 3.141592654
let area myShape =
match myShape with
| Circle radius -> pi * radius * radius
| Square s -> s * s
| Rectangle (length , width) -> length * width
let radius = 8.0
let myCircle = Circle(radius)
printfn "Area of circle with radius %g: %g" radius (area myCircle)
let side = 12.0
let mySquare = Square(side)
printfn "Area of square that has side %g: %g" side (area mySquare)
let length , width = 3.0, 5.0
let myRectangle = Rectangle(length , width)
printfn "Area of rectangle with length %g and width %g is %g" length width (area myRectangle)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

E a saída será a seguinte:

Area of circle with radius 8: 201.061929856
Area of square that has side 12: 144
Area of rectangle with length 3 and width 5 is 15

Exemplo de Explicação:

Este código F# define uma união discriminada chamada Shape com três casos: Circle , Square e Rectangle . Cada caso contém diferentes tipos de dados, como um raio para o caso Círculo e comprimento e largura para o caso Retângulo .

O código também define uma função chamada area que recebe uma Shape como entrada e retorna a área dessa forma. A função de área usa correspondência de padrão para lidar com cada caso da união de forma e calcular a área da forma correspondente.

O código então cria instâncias de Shape usando cada caso e imprime a área de cada forma usando a função de área . A função printfn formata e imprime os resultados no console.

Por exemplo, quando o código é executado, ele cria um círculo com um raio de 8,0 e calcula sua área usando a função de área . O código então imprime o resultado no console no formato “Área do círculo com raio 8.0: <área>”. Ele faz o mesmo para um quadrado com comprimento de lado de 12,0 e um retângulo com comprimento de 3,0 e largura de 5,0.

Este código demonstra o poder e a flexibilidade das uniões discriminadas em F# para modelar estruturas de dados e algoritmos complexos.


Método de pagamento usando o tipo de escolha

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type PaymentMethod =
| CreditCard of string * int * string
| PayPal of string
| BankTransfer of string * string
let printPaymentMethod (method: PaymentMethod) =
match method with
| CreditCard (cardType, number, expiration) ->
printfn "Credit card \nPayment method: %s \ncard ending at: %i \nexpiring on: %s" cardType number expiration
| PayPal email ->
printfn "\nPayPal payment method: %s" email
| BankTransfer (bankName, accountNumber) ->
printfn "\nBank transfer \nPayment method: account %s at bank %s" accountNumber bankName
let creditcard = CreditCard("Purchase cards", 421215, "02/03/2025")
printPaymentMethod creditcard
let paypal = PayPal("[email protected]")
printPaymentMethod paypal
let bank = BankTransfer("JPMorgan Chase","02230017345")
printPaymentMethod bank
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

E a saída será:

Credit card
Payment method: Purchase cards
card ending at: 421215
expiring on: 02/03/2025

PayPal payment method: [email protected]

Bank transfer
Payment method: account 02230017345 at bank JPMorgan Chase

Se você gostou deste artigo e o achou informativo sobre a linguagem de programação funcional F#, você pode deixar seu feedback reagindo abaixo.

Nós valorizamos o seu feedback.
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0

Assine a nossa newsletter
Digite seu e-mail para receber um resumo semanal de nossos melhores posts. Saber mais!
ícone