Skip to content

Instantly share code, notes, and snippets.

@carlosble
Created October 4, 2021 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlosble/b4273e705a5683029c4c1d3fe6326fd5 to your computer and use it in GitHub Desktop.
Save carlosble/b4273e705a5683029c4c1d3fe6326fd5 to your computer and use it in GitHub Desktop.
Ejemplo F# de uniones discriminadas y productos
type Percentage = Percentage of float
type ResidentDiscount = ResidentDiscount of Percentage
type FamilyDiscount = FamilyDiscount of Percentage
type SpecialResidentDiscount = SpecialResidentDiscount of Percentage
type BussinesClub = BussinesClub of Percentage
type SpanishSubsidy =
| SpecialResident of SpecialResidentDiscount
| Resident of ResidentDiscount
| Family of FamilyDiscount
type FlightDiscount =
| Subsidy of SpanishSubsidy
| Bussines of BussinesClub
| SubsidyPlusBussines of ResidentDiscount * BussinesClub
| NoDiscount
type FlightOrderRequest = {
SpanishSubsidy: SpanishSubsidy option
BussinesClub: BussinesClub option
// passenger info over here...
}
type CalculateDiscountPercentage = FlightDiscount -> Percentage
type DiscountFromOrder = FlightOrderRequest -> FlightDiscount
module Percentage =
let add p1 p2 =
let (Percentage a) = p1
let (Percentage b) = p2
let sum = a + b
Percentage sum
let zero =
Percentage(0.0)
let value (Percentage percentage) = percentage
let max p1 p2 =
let (Percentage a) = p1
let (Percentage b) = p2
if (a > b) then
p1
else
p2
module ResidentDiscount =
let create : ResidentDiscount =
ResidentDiscount (Percentage 75.0)
let percentage (ResidentDiscount p) = p
module FamilyDiscount =
let create : FamilyDiscount =
FamilyDiscount (Percentage 10.0)
let percentage (FamilyDiscount p) = p
module SpecialResidentDiscount =
let create : SpecialResidentDiscount =
SpecialResidentDiscount (Percentage 75.0)
let percentage (SpecialResidentDiscount p) = p
module SpanishSubsidy =
let percentage (subsidy: SpanishSubsidy) =
match subsidy with
| SpecialResident (d) -> SpecialResidentDiscount.percentage d
| Resident (d) -> ResidentDiscount.percentage d
| Family (d) -> FamilyDiscount.percentage d
module BussinesClub =
let create : BussinesClub =
BussinesClub (Percentage 20.0)
let cumulativePercentage (bussines: BussinesClub) (resident: ResidentDiscount) =
let (BussinesClub p1) = bussines
let (ResidentDiscount p2) = resident
Percentage.add (Percentage.max p1 p2) (Percentage 10.0)
let percentage (BussinesClub p) = p
let discountFromOrder : DiscountFromOrder =
fun request ->
match request.BussinesClub with
| Some(bussinesClub) ->
match request.SpanishSubsidy with
| Some(subsidy) ->
match subsidy with
| Resident (rd) -> SubsidyPlusBussines (rd, request.BussinesClub.Value)
| _ -> Subsidy (subsidy)
| None -> Bussines (request.BussinesClub.Value)
| None ->
match request.SpanishSubsidy with
| Some(subsidy) -> Subsidy (subsidy)
| None -> NoDiscount
let calculatePercentage : CalculateDiscountPercentage =
fun discount ->
match discount with
| Subsidy (s) -> SpanishSubsidy.percentage s
| Bussines (b) -> BussinesClub.percentage b
| SubsidyPlusBussines (s, b) -> BussinesClub.cumulativePercentage b s
| NoDiscount -> Percentage.zero
// ----------------------------------------------------------------
// USAGE EXAMPLES:
// ----------------------------------------------------------------
let flightOrder : FlightOrderRequest = {
SpanishSubsidy = Family FamilyDiscount.create |> Some;
BussinesClub = None
}
let flightOrder2 : FlightOrderRequest = {
SpanishSubsidy = Resident ResidentDiscount.create |> Some;
BussinesClub = Some BussinesClub.create;
}
let discount = discountFromOrder flightOrder
printfn "Discount1: %A" discount
let discount2 = discountFromOrder flightOrder2
printfn "Discount2: %A" discount2
printfn "Calculated percentage: %A" (calculatePercentage discount)
printfn "Calculated percentage: %A" (calculatePercentage discount2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment