All Downloads are FREE. Search and download functionalities are using the official Maven repository.

libretto.examples.coffeemachine.CoffeeMachineProvider.scala Maven / Gradle / Ivy

The newest version!
package libretto.examples.coffeemachine

import libretto.scaletto.StarterKit.*
import libretto.scaletto.StarterKit.scalettoLib.given

object CoffeeMachineProvider {
  import Protocol.*

  val makeCoffeeMachine: Done -⚬ CoffeeMachine = rec { self =>
    val returnAndRepeat: Val[Beverage] -⚬ (Val[Beverage] |*| CoffeeMachine) =
      signalDone >
        λ { case (beverage |*| beverageDone) =>
          val nextMachine: $[CoffeeMachine] = when(beverageDone) { self }
          beverage |*| nextMachine
        }

    CoffeeMachine.create(
      serveEspresso > out(returnAndRepeat),
      serveLatte    > out(returnAndRepeat),
    )
  }

  private def serveEspresso: Done -⚬ (EspressoOptions =⚬ Val[Beverage]) =
    λ { ready =>
      λ.closure { espressoOptions =>
        (espressoOptions waitFor ready) |> makeEspresso
      }
    }

  private def serveLatte: Done -⚬ (LatteOptions =⚬ Val[Beverage]) =
    λ { ready =>
      λ.closure { latteOptions =>
        (latteSpec(latteOptions) waitFor ready) |> makeLatte
      }
    }

  private type LatteSpec = (Size, ShotCount, Option[Flavor])

  private def makeEspresso: EspressoOptions -⚬ Val[Beverage] =
    mapVal(espresso)

  private def makeLatte: Val[LatteSpec] -⚬ Val[Beverage] =
    mapVal(latte)

  private def latteSpec: LatteOptions -⚬ Val[LatteSpec] =
    λ { case size |*| shotCount |*| flavor =>
      unliftPair(unliftPair(size |*| shotCount) |*| flavor) |> mapVal {
        case ((a, b), c) => (a, b, c)
      }
    }

  private def espresso(shots: ShotCount): Beverage =
    Beverage("Espresso" + (shots match {
      case ShotCount.Double => " doppio"
      case ShotCount.Single => ""
    }))

  private def latte(params: LatteSpec): Beverage = {
    val (size, shots, flavor) = params
    val flavorStr = flavor.map(_.toString.toLowerCase + " ").getOrElse("")
    val shotsStr = shots match {
      case ShotCount.Double => " with an extra shot"
      case ShotCount.Single => ""
    }
    Beverage(s"$size ${flavorStr}latte$shotsStr")
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy