.uniform.core_sjs0.6_2.11.4.10.0.source-code.Language.scala Maven / Gradle / Ivy
package ltbs.uniform
import scala.language.higherKinds
import shapeless.HList
import com.github.ghik.silencer.silent
import validation.Rule
import cats.Functor
/** The core language of uniform, journeys will typically be expressed
* in terms of this interaction
*
* {{{
* import ltbs.uniform._
* import scala.language.higherKinds
*
* // the data types that the user can be presented with in a `tell'
* type TellTypes = String :: Option[String] :: NilTypes
*
* // the data types that the user can be prompted for in an `ask'
* type AskTypes = Int :: Option[String] :: NilTypes
*
* def program[F[_]: Monad](
* interpreter: Language[F, TellTypes, AskTypes]
* ): F[(Int, Option[String])] = {
* import interpreter._
* for {
* a <- interact[String,Int]("ask-a", "please provide a")
* b <- interact[String,Int]("ask-b", "please provide b")
* c <- ask[Option[String]]("c")
* _ <- tell[Option[String]]("d", c)
* } yield ((a + b, c))
* }
* }}}
*/
trait Language[UF[_], SupportedTell <: HList, SupportedAsk <: HList]{
/** Nest a journey within a single stage of a bigger journey. */
def subJourney[A](@silent("never used") id: String*)(sub: => UF[A]): UF[A] = sub
/** Present an instance of Tell to the user, and ask for an
* instance of Ask. Defines a 'step' in the user journey.
*
* {{{
* val askAddr: UF[Address] =
* interpreter.interact[Address,Boolean](
* "confirm-address",
* someAddress
* )
* }}}
*
* @param id step identifier - care should be taken to keep these
* distinct within a given journey
* @param tell data to be presented to the user
* @param default optional existing/default value. For example an
* 'edit' journey.
* @param validation rule to check the data is valid (after it has
* been turned into an Ask).
* @param customContent overrides any messages used in the journey
* step
*/
def interact[Tell, Ask](
id: String,
tell: Tell,
default: Option[Ask] = None,
validation: Rule[Ask] = Rule.alwaysPass[Ask],
customContent: Map[String,(String,List[Any])] = Map.empty
)(
implicit
selectorTell : IndexOf[SupportedTell, Tell],
selectorAsk : IndexOf[SupportedAsk, Ask]
): UF[Ask]
/**
* Ask the user for an instance of A. This is equivalent
* to `interact[Unit, A]`
*
* {{{
* val askAddr: UF[Address] =
* interpreter.ask[Address]("delivery-address")
* }}}
*
* @param id step identifier - care should be taken to keep these
* distinct within a given journey
* @param default optional existing/default value. For example an
* 'edit' journey.
* @param validation rules to check the data is valid (after it has
* been turned into an Ask).
* @param customContent overrides any messages used in the journey
* step
*
*/
def ask[A](
id: String,
default: Option[A] = None,
validation: Rule[A] = Rule.alwaysPass[A],
customContent: Map[String,(String,List[Any])] = Map.empty
)(
implicit selectorAsk : IndexOf[SupportedAsk, A],
selectorTell : IndexOf[SupportedTell, Unit]
) = interact[Unit,A](id, (), default, validation, customContent)
/**
* Present the user with an instance of A. This is equivalent
* to `interact[A, Unit]`
*
* {{{
* val askAddr: UF[Unit] =
* interpreter.tell[OrderConfimation](
* "order-confirmation",
* myOrder.getConfirmation
* )
* }}}
*
* @param id step identifier - care should be taken to keep these
* distinct within a given journey
* @param tell data to be presented to the user
* @param customContent overrides any messages used in the journey
* step
*/
def tell[A](
id: String,
tell: A,
customContent: Map[String,(String,List[Any])] = Map.empty
)(
implicit selectorAsk : IndexOf[SupportedAsk, Unit],
selectorTell : IndexOf[SupportedTell, A]
) = interact[A,Unit](id, tell, customContent=customContent)
def end[A](
id: String,
tellValue: A,
customContent: Map[String,(String,List[Any])] = Map.empty
)(
implicit selectorAsk : IndexOf[SupportedAsk, Unit],
selectorTell : IndexOf[SupportedTell, A],
ufFunctor: Functor[UF]
): UF[Nothing] = {
import cats.syntax.functor._
tell[A](id, tellValue, customContent=customContent) map {
_ => throw new IllegalStateException(s"Journey end at $id")
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy