For building DSLs (Domain-Specific Languages) that allow the composition of pure and fully type-safe expressions such that any sub-expression may generate or receive errors as input, short-circuiting evaluation. Such DSLs include support for readers that can read for weakly-typed (i.e. "unsafe") data sources.
resolvers ++= Seq(
"jitpack" at "https://jitpack.io"
)
libraryDependencies ++= Seq(
"com.github.ryanonsrc" % "espresso" % "v1.1.4"
)
espresso makes extensive use of the Typelevel cats and shapeless libraries as well as the kind-projector compiler plugin.
Take a look at https://github.com/ryanonsrc/espresso/tree/master/src/test/scala/io/nary/espresso/sample
Term[E, A]
- represents a term within an expression, evaluating to an error of typeE
or result of typeA
Expr[E, A, B]
- for any expression taking a value of typeA
and evaluating to either a result of typeB
or an error of typeE
In[E, A]
- weakly-typedAny
input from "the outside world" that can be "read" into an expression as either value of typeA
or an error of typeE
opN[E, A1, ... AN, B]
- wraps an operation:(Term[E, A1],...,Term[E, AN]) => (Term[E, B])
produces anExpr[E, (A1,...,AN), B]
joinN[E, A, B1, ... BN]
- combine an tuple ofN
expressions:Expr[E, A, Bi]
into a singleExpr[E, A, (B1,...,BN)]
evalN[E, A, B1, ... BN, C]
- GivenN
expressions:Expr[E, A, Bi]
and operation:Expr[E, (B1,...,BN), C]
, generateExpr[E, A, C]
const[E, A, B]
- lift a value of typeB
directly into an expression (bypassing the need to read from a weakly-typed sourceA
)error[E, A, B]
- lift an error instance of typeE
directly into an expression (bypassing the need to read from a weakly-typed sourceA
)funcExprN[E, A1,... AN, B]
- lift functions of type(A1, ..., AN) => B
String => E
(for errors) into the expression:Expr[E, (A1,...,AN), B]
create any implicit readers/conversions needed for "reading" values from Source using the espresso.adapters.reader
:
-
def read[E, A, K, S](k: K, orElse: E, f: S => K => In[E, A] => Option[Term[E, A]]) (using i: In[E, A]): Expr[E, S, A]
- define your library of
Expr[E, A, B]
operations either usingopN
-wrappers or lifted-funcExprN
s - create your DSL syntax in the form of an
extension
of l-Expr[<Your DSL Error type>, <Your DSL expression data source type>, <Your DSL produced value type>]
as functions that will evaluate the l-Expr
with a provided library function using anevalN
combinator