feat(manual): document predicate and constraints
This commit is contained in:
@@ -265,7 +265,9 @@ type Money = float
|
|||||||
type Income = Money where _ >= 0
|
type Income = Money where _ >= 0
|
||||||
```
|
```
|
||||||
|
|
||||||
Constraints can be combined with any type using the `where` keyword, followed by a predicate expression (see @predicate-stmt).
|
Constraints can be combined with any type using the `where` keyword, followed by a constraint expression (see @constraint-expr).
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
|
||||||
== Extend Statement <extend-stmt>
|
== Extend Statement <extend-stmt>
|
||||||
|
|
||||||
@@ -302,15 +304,60 @@ extend Container[T <: float] {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
|
||||||
== Predicate Statement <predicate-stmt>
|
== Predicate Statement <predicate-stmt>
|
||||||
|
|
||||||
|
A *`predicate`* statement lets you define a named constraint expression, like a function, which can then be used in other constraint expressions (either in other predicate statements or in constraint types). See @constraint-expr for more information about the syntax of constraint expressions.
|
||||||
|
|
||||||
|
The left-hand side of a predicate statement is written as a function signature, without a return type. The right-hand side is a constraint expression. For example:
|
||||||
|
```midas
|
||||||
|
predicate is_positive(v: float) = v >= 0
|
||||||
|
```
|
||||||
|
|
||||||
|
The left-hand side can also be curried to allow partial application. For example:
|
||||||
|
```midas
|
||||||
|
predicate in_range(mn: float, mx: float)(v: float) = mn <= v & v <= mx
|
||||||
|
predicate is_ratio = in_range(0.0, 1.0)
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that the second predicate statement doesn't take any parameters. This is simply a partial application of another predicate, kind of like an alias. You can use it in other expressions to finalize the call:
|
||||||
|
```midas
|
||||||
|
type Efficiency = float where is_ratio(_)
|
||||||
|
```
|
||||||
|
|
||||||
|
Of course you can also directly call `in_range`:
|
||||||
|
```midas
|
||||||
|
type Efficiency = float where in_range(0.0, 1.0)(_)
|
||||||
|
```
|
||||||
|
|
||||||
|
When compiled, named predicates are translated to Python functions which are used in runtime assertions. Only predicates that are referenced are compiled.
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
== Constraint Expressions <constraint-expr>
|
||||||
|
|
||||||
|
*Constraint expressions* are Python-like expressions which can appear in *`predicate`* statements or in constraint types.
|
||||||
|
|
||||||
|
They can contain comparisons, simple computations, logical operations and must evaluate to a boolean value.
|
||||||
|
|
||||||
|
Context is quite restricted inside these expressions. You can only reference some builtin functions, such as type constructors (`float(...)`, `str(...)`, etc.), parameters of predicate statements, and named predicates. In constraint type, the special variable `_` can be used to reference the value targeted by the type. For example:
|
||||||
|
|
||||||
|
#codly()
|
||||||
|
#figure(
|
||||||
|
```midas
|
||||||
|
predicate not_nan(v: float) = v != float("nan")
|
||||||
|
type RealFloat = float where not_nan(_)
|
||||||
|
```,
|
||||||
|
caption: [Example constraint expressions],
|
||||||
|
) <ex-constraint-expr>
|
||||||
|
|
||||||
|
In the predicate statement (@ex-constraint-expr:1), we reference the parameter `v` and the builtin `float` function.
|
||||||
|
In the constraint type definition (@ex-constraint-expr:2), we then reference the named predicate `not_nan`, passing the value targeted by the type itself ( `_` )
|
||||||
|
|
||||||
|
= Supported Python Syntax <python-ref>
|
||||||
|
|
||||||
#TODO
|
#TODO
|
||||||
|
|
||||||
== Casts <cast>
|
== Casts <cast>
|
||||||
|
|
||||||
#TODO
|
#TODO
|
||||||
|
|
||||||
= Supported Python Syntax <python-ref>
|
|
||||||
|
|
||||||
#TODO
|
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,10 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#let _unshift-prefix(prefix, content) = context {
|
||||||
|
pad(left: -measure(prefix).width, prefix + content)
|
||||||
|
}
|
||||||
|
|
||||||
#let project(
|
#let project(
|
||||||
title: none,
|
title: none,
|
||||||
author: none,
|
author: none,
|
||||||
@@ -64,9 +68,28 @@
|
|||||||
|
|
||||||
show std.title: set text(size: 1.5em)
|
show std.title: set text(size: 1.5em)
|
||||||
|
|
||||||
|
// Adapted from https://github.com/hei-templates/hei-synd-thesis/blob/7d2b941197babae0bf3afd4e5914754e09a64001/lib/template-thesis.typ#L242-L261
|
||||||
show heading.where(level: 1): it => {
|
show heading.where(level: 1): it => {
|
||||||
pagebreak()
|
pagebreak()
|
||||||
it
|
|
||||||
|
set text(size: 1.5em)
|
||||||
|
set block(above: 1.2em, below: 1.2em)
|
||||||
|
if it.numbering != none {
|
||||||
|
let num = numbering(it.numbering, ..counter(heading).at(it.location()))
|
||||||
|
let prefix = num + h(1em)
|
||||||
|
_unshift-prefix(prefix, it.body)
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
show heading.where(level: 2): it => {
|
||||||
|
if it.numbering != none {
|
||||||
|
let num = numbering(it.numbering, ..counter(heading).at(it.location()))
|
||||||
|
_unshift-prefix(num + h(0.8em), it.body)
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set page(
|
set page(
|
||||||
|
|||||||
Reference in New Issue
Block a user