Last active
December 8, 2022 23:04
-
-
Save dawedawe/6911cf7eef8e8491b01e49ddf83e6c86 to your computer and use it in GitHub Desktop.
Tortilla CE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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