Skip to content

Instantly share code, notes, and snippets.

@dawedawe
Last active December 8, 2022 23:04
Show Gist options
  • Save dawedawe/6911cf7eef8e8491b01e49ddf83e6c86 to your computer and use it in GitHub Desktop.
Save dawedawe/6911cf7eef8e8491b01e49ddf83e6c86 to your computer and use it in GitHub Desktop.
Tortilla CE
module Model =
open System.Collections.Generic
type Feature =
| Empty
| Meat
| MeatStrips
| NoMeatStrips
| Cheese
| Rice
| NoRice
| Soup
| SauceOnTop
| NoSauceOnTop
type Fixings =
private
| Features of Feature Set
static member Create = Features Set.empty
module Fixings =
let add (fixings: Fixings) (toAdd: Feature) =
match (toAdd, fixings) with
| (Empty, Features fs) when not (Set.isEmpty fs) -> System.InvalidOperationException() |> raise
| (MeatStrips, Features fs) when Set.contains NoMeatStrips fs -> System.InvalidOperationException() |> raise
| (NoMeatStrips, Features fs) when Set.contains MeatStrips fs -> System.InvalidOperationException() |> raise
| (Rice, Features fs) when Set.contains NoRice fs -> System.InvalidOperationException() |> raise
| (NoRice, Features fs) when Set.contains Rice fs -> System.InvalidOperationException() |> raise
| (SauceOnTop, Features fs) when Set.contains NoSauceOnTop fs -> System.InvalidOperationException() |> raise
| (NoSauceOnTop, Features fs) when Set.contains SauceOnTop fs -> System.InvalidOperationException() |> raise
| (f, Features fs) -> Features(Set.add f fs)
let adheresTo (fixings: Fixings) (wanted: Feature list) =
match fixings with
| Features fs when fs = Set.ofList wanted -> true
| _ -> false
type Folding =
| Roundish
| FlatFolded
type Fried = bool
type SizeAndShape =
| SmallTrianglesOvalsOrRectangles
| RolledUp
| Handsized
| Round
type Condition =
| Crunchy
| Soft
type Dish =
| Nachos
| Taquito
| Taco
| EmptyTacoShell
| TortillaSoup
| Fajita
| Enchilada
| Quesadilla
| Burrito
| Chimichanga
| Tostada
type Tortilla =
{ Condition: Condition option
Folding: Folding option
Fried: Fried option
Fixings: Fixings option
SizeAndShape: SizeAndShape option
Dish: Dish option }
module Tortilla =
open Model
let (|ItsNachos|ItsTostada|ItsTaquito|ItsTaco|ItsEmptyTacoShell|ItsNone|) model =
match (model.Condition, model.Folding, model.Fried, model.Fixings, model.SizeAndShape) with
| (Some Crunchy, None, None, None, Some SmallTrianglesOvalsOrRectangles) -> ItsNachos
| (Some Crunchy, None, None, None, Some Round) -> ItsTostada
| (Some Crunchy, None, None, None, Some RolledUp) -> ItsTaquito
| (Some Crunchy, None, None, Some fs, Some Handsized) when Fixings.adheresTo fs [ Meat ] -> ItsTaco
| (Some Soft, Some Roundish, Some false, Some fs, _) when Fixings.adheresTo fs [ Meat; NoRice ] -> ItsTaco
| (Some Soft, Some FlatFolded, None, Some fs, _) when Fixings.adheresTo fs [ Meat; NoRice; NoMeatStrips ] -> ItsTaco
| (Some Crunchy, None, None, Some fs, Some Handsized) when Fixings.adheresTo fs [ Empty ] -> ItsEmptyTacoShell
| _ -> ItsNone
let (|ItsTortillaSoup|ItsQuesadilla|ItsBurrito|ItsChimichanga|ItsEnchilada|ItsFajita|ItsNone|) model =
match (model.Condition, model.Folding, model.Fried, model.Fixings, model.SizeAndShape) with
| (Some Soft, None, None, Some fs, None) when Fixings.adheresTo fs [ Soup ] -> ItsTortillaSoup
| (Some Soft, None, None, Some fs, None) when Fixings.adheresTo fs [ Cheese ] -> ItsQuesadilla
| (Some Soft, None, Some false, Some fs, None) when Fixings.adheresTo fs [ Meat; Rice ] -> ItsBurrito
| (Some Soft, None, Some true, Some fs, None) when Fixings.adheresTo fs [ Meat; Rice ] -> ItsChimichanga
| (Some Soft, Some Roundish, Some true, Some fs, None) when Fixings.adheresTo fs [ Meat; NoRice ] -> ItsChimichanga
| (Some Soft, Some FlatFolded, None, Some fs, None) when Fixings.adheresTo fs [ Meat; NoRice; MeatStrips; SauceOnTop ] -> ItsEnchilada
| (Some Soft, Some FlatFolded, None, Some fs, None) when Fixings.adheresTo fs [ Meat; NoRice; MeatStrips; NoSauceOnTop ] -> ItsFajita
| _ -> ItsNone
let determineDish model =
match model with
| ItsNachos -> Some Nachos
| ItsTostada -> Some Tostada
| ItsTaquito -> Some Taquito
| ItsTaco -> Some Taco
| ItsEmptyTacoShell -> Some EmptyTacoShell
| ItsTortillaSoup -> Some TortillaSoup
| ItsQuesadilla -> Some Quesadilla
| ItsBurrito -> Some Burrito
| ItsChimichanga -> Some Chimichanga
| ItsEnchilada -> Some Enchilada
| ItsFajita -> Some Fajita
| _ -> None
type TortillaBuilder() =
member _.Yield _ =
{ Condition = None
Folding = None
Fried = None
Fixings = None
SizeAndShape = None
Dish = None }
[<CustomOperation "condition">]
member _.Condition (state:Tortilla, condition) = { state with Condition = Some condition }
[<CustomOperation "folding">]
member _.Folding (state:Tortilla, folding) = { state with Folding = Some folding }
[<CustomOperation "fried">]
member _.Fried (state:Tortilla) = { state with Fried = Some true }
[<CustomOperation "notfried">]
member _.NotFried (state:Tortilla) = { state with Fried = Some false }
[<CustomOperation "add">]
member _.AddFixing (state:Tortilla, fixing) =
match state.Fixings with
| None -> { state with Fixings = Some (Fixings.add Fixings.Create fixing) }
| Some fixings -> { state with Fixings = Some (Fixings.add fixings fixing) }
[<CustomOperation "sizeAndShape">]
member _.SizeAndShape (state:Tortilla, sizeAndShape) = { state with SizeAndShape = Some sizeAndShape }
let tortilla = TortillaBuilder()
open Tortilla
open Model
let t = tortilla {
condition Soft
add Meat
add Rice
notfried
}
printfn "%A" (determineDish t)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment