Predicates (Unified Model)
4.1 Predicate expressions
Any expression of type Bool that uses only:
- literals
- field access
- patterns
- the implicit
_
is a predicate expression.
Examples:
price > 80
_.price > 80
email == Some "x"
Some _
Ok { value } when value > 10Pattern predicates like Ok { value } when value > 10 are “match tests”: they succeed if the current value matches the pattern, and the when guard can refer to names bound by the pattern.
4.1.1 Predicate combinators
Predicate expressions support the usual boolean operators:
!p(not)p && q(and, short-circuit)p || q(or, short-circuit)
These operators may appear inside any predicate position (including generator guards and patch predicates).
If you want to name predicate functions explicitly, you can treat them as ordinary functions:
Pred A = A => Bool
andPred : Pred A -> Pred A -> Pred A
andPred p q = x => p x && q x
isActive : Pred User
isActive = .active
isPremium : Pred User
isPremium = u => u.tier == Premium
isActivePremium : Pred User
isActivePremium = andPred isActive isPremium4.2 Implicit binding rule
Inside a predicate expression:
_is bound to the current element- bare field names are resolved as
_.field .fieldis an accessor function (x => x.field), not a field value
TIP
filter active is shorthand for filter (_.active) when active is a boolean field. If active is bound in scope, it refers to that binding instead.
price > 80 // _.price > 80
active // _.active4.3 Predicate lifting
Whenever a function expects:
A => Boola predicate expression may be supplied.
NOTE
Predicates can also perform complex transformations by deconstructing multiple fields: map { name, id } => if id > 10 then name else "no name"
Desugaring:
predicateExpr
⇒ (_ => predicateExpr)Applies to:
filter,find,takeWhile,dropWhile- generator guards (
x -> pred) - patch predicates
- user-defined functions
Examples:
users |> filter active
users |> filter (age > 18)
users |> find (email == Some "x")
xs |> takeWhile (_ < 10)
xs |> dropWhile (_ < 0)generate {
u <- users
u -> active && tier == Premium
yield u
}store <| { items[price > 80].discount: 0.1 }
store <| { categories[name == "Hardware"].items[active].price: _ * 1.1 }where : (A => Bool) -> List A -> List A
where pred xs = xs |> filter pred
admins = where (role == Admin) users
activeUsers = where active users4.4 No automatic lifting in predicates
Predicates do not auto-lift over Option or Result.
filter (email == "x") // ❌ if email : Option Text
filter (email == Some "x") // ✅Reason: predicates affect cardinality.