Skip to content

Instantly share code, notes, and snippets.

@iSeiryu
Last active May 2, 2024 15:43
Show Gist options
  • Save iSeiryu/714dd5fe267fdd2b684470da75d27a2d to your computer and use it in GitHub Desktop.
Save iSeiryu/714dd5fe267fdd2b684470da75d27a2d to your computer and use it in GitHub Desktop.
C# vs F# pattern matching
// F#

type BodyType = 
    | Sedan
    | SUV

type Vehicle =
    | Bus of riders:int * capacity:int * basePrice:decimal
    | Taxi of riders:int * capacity:int * basePrice:decimal * body:BodyType * fares:int
    | Train of riders:int * capacity:int * basePrice:decimal

let vehicle = Bus(riders = 10, capacity = 30, basePrice = 5.00m)

let calculateToll vehicle =
    match vehicle with
    | Bus(r,c,p) when (double r / double c) < 0.50 -> p + 2.00m
    | Bus(r,c,p) when (double r / double c) > 0.90 -> p - 1.00m
    | Bus(basePrice = p) -> p

    | Taxi(basePrice = p; body = b) when b = SUV   -> p + 1.00m
    | Taxi(basePrice = p; body = b) when b = Sedan -> p

    | Train(basePrice = p; capacity = c) when c = 20 -> p * 1.2m
    | Train(basePrice = p) -> p
    | _ -> 0m
// C#

Vehicle vehicle = new Bus(Riders: 10, Capacity: 20, BasePrice: 5.00m);
decimal CalculateToll(Vehicle vehicle) => vehicle switch {
    Bus b when ((double)b.Riders / b.Capacity) < 0.50 => b.BasePrice + 2.00m,
    Bus b when ((double)b.Riders / b.Capacity) > 0.90 => b.BasePrice - 1.00m,
    Bus b => b.BasePrice,

    Taxi { Body: BodyType.SUV } t   => t.BasePrice + 1.00m,
    Taxi { Body: BodyType.Sedan } t => t.BasePrice,

    Train { Capacity: 20 } t => t.BasePrice * 1.2m,
    Train t => t.BasePrice,

    { } => 0m,
    _ => throw new ArgumentException(message: "Not a known vehicle type", paramName: nameof(vehicle))
};

public record Vehicle(int Riders, int Capacity, decimal BasePrice);
public record Bus(int Riders, int Capacity, decimal BasePrice) : Vehicle(Riders, Capacity, BasePrice);
public record Train(int Riders, int Capacity, decimal BasePrice) : Vehicle(Riders, Capacity, BasePrice);
public record Taxi(int Riders, int Capacity, decimal BasePrice, BodyType Body, int Fares) : Vehicle(Riders, Capacity, BasePrice);
public enum BodyType {
    Sedan,
    SUV
}
@JordanMarr
Copy link

module VehicleToll

type BodyType = | Sedan | SUV
type Bus = { Riders: int; Capacity: int; BasePrice: decimal }
type Taxi = { Riders: int; Capcity: int; BasePrice: decimal; Body: BodyType; Fares: int } 
type Train = { Riders: int; Capacity: int; BasePrice: decimal }

type Vehicle =
    | Bus of Bus
    | Taxi of Taxi
    | Train of Train

let calculateToll vehicle = 
    match vehicle with
    | Bus bus when double bus.Riders / double bus. Capacity < 0.50 -> bus.BasePrice + 2.00m
    | Bus bus when double bus.Riders / double bus. Capacity > 0.90 -> bus.BasePrice - 1.00m
    | Bus bus -> bus.BasePrice
    | Taxi ({ Body = SUV } as taxi) -> taxi.BasePrice + 1.00m
    | Taxi ({ Body = Sedan } as taxi) -> taxi.BasePrice
    | Train ({ Capacity = 20 } as train) -> train.BasePrice + 1.20m
    | Train train -> train.BasePrice

@pkese
Copy link

pkese commented May 2, 2024

type BodyType =
    | Sedan
    | SUV

type Vehicle =
    | Bus of riders:int * capacity:int * basePrice:decimal
    | Taxi of riders:int * capacity:int * basePrice:decimal * body:BodyType * fares:int
    | Train of riders:int * capacity:int * basePrice:decimal

let vehicle = Bus(riders = 10, capacity = 30, basePrice = 5.00m)

let calculateToll vehicle =
    match vehicle with
    | Bus  (r, c, p) when (double r / double c) < 0.50 -> p + 2.00m
    | Bus  (r, c, p) when (double r / double c) > 0.90 -> p - 1.00m
    | Bus  (r, c, p) -> p
    | Taxi (r, c, p, SUV, f) -> p + 1.00m
    | Taxi (r, c, p, Sedan, f) -> p
    | Train(r,20, p) -> p * 1.2m
    | Train(r, c, p) -> p
    | _ -> 0m   // <-- editor tooling then notifies, that this is unnecessary

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment