Effect Schema Lifting¶
class_directed_lifts(base_schema, effect) and lift_rule_set(base_schemas, effects): emit lifted SchemaDecls for every typeclass an effect inhabits.
effect_lifts
¶
Class-driven schema lifting for effect-typed parsers.
The class_directed_lifts function takes a base
SchemaDecl and an effect instance and returns a tuple of
lifted SchemaDecl instances — one per typeclass-class the
effect inhabits.
The dispatch key is the typeclass interface, never the effect's
concrete identity. Adding a new effect (or a new typeclass) extends
the lifting machinery automatically: every effect that registers
against Functor gets fmap lifts; every effect that
additionally registers against Applicative also gets
apply lifts; every Monad gets bind lifts; and so
on across both the monad-style and arrow-style towers.
The lifted schemas are SchemaDecl instances and feed into
the same PatternBinarySchema / PatternUnarySchema
machinery as user-written schemas; the chart-fixed-point machinery in
quivers.stochastic.parsers consumes them uniformly with the
base schemas. The chart cells are indexed by (Cat, EffectStack)
pairs, and at each cell the parser fires:
- Base schemas between effect-pure cells (the classical Lambek case).
- Lift schemas when one or more children carry effect prefixes
that the schema's domain doesn't (this is what
class_directed_liftsproduces). - Handler firings when an applicable handler is registered, reducing an effect-typed cell to a less-effect-typed cell.
- Commutation firings when a registered distributive law swaps sibling effect orderings.
References
- Bumford, D. and Charlow, S. (2026). Effect-Driven Interpretation: Functors for Natural Language Composition. Cambridge Elements in Semantics. Cambridge University Press. Online ISBN 9781009285377; preprint arXiv:2504.00316.
class_directed_lifts
¶
class_directed_lifts(base_schema: SchemaDecl, effect: object) -> tuple[SchemaDecl, ...]
Generate the class-driven lifts for base_schema under effect.
Dispatches on which typeclasses the effect inhabits — Functor,
Applicative, Monad, Alternative, MonadPlus, ArrowApply, ArrowLoop,
and so on — and emits one or more SchemaDecl instances
per class. The lifts compose with the base schema in the chart
parser's joint type-and-effect dispatch.
Lifts emitted (when the corresponding class is inhabited):
Applicative:pure_T+apply_T.Monad(andApplicative): addsbind_T.Alternative: addsalt_T.MonadPlus: union of Monad and Alternative lifts.
Functor-only effects produce pure_T-shape lifts only when the
instance also implements Applicative; bare Functor
instances need a separate fmap_T shape (analogous to
apply_T but with one functor-typed premise rather than two).
Arrow-side lifts (arr_T, first_T, loop_T) are emitted
by a parallel branch that introspects the effect's arrow-tower
membership; see the # arrow lifts block below.
| PARAMETER | DESCRIPTION |
|---|---|
base_schema
|
The base schema being lifted.
TYPE:
|
effect
|
An effect instance (any class registered against the relevant
typeclass ABCs in
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple of SchemaDecl
|
Zero or more lifted schemas, ordered from weakest typeclass (Applicative) through strongest (MonadPlus + ArrowApply + ArrowLoop). |
Source code in src/quivers/stochastic/effect_lifts.py
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | |
make_swap_schema
¶
make_swap_schema(distributive_law: object, base_schema: SchemaDecl | None = None) -> SchemaDecl
Generate a swap_TU schema from a registered distributive law.
Given a DistributiveLaw λ : S ∘ T ⇒ T ∘ S, the chart
parser uses swap_TU to exchange sibling effect orderings at a
cell whose effect stack ends in T·U:
swap_TU[X : Cat] : T(U(X)) -> U(T(X))
The schema is consumed by the chart's commutation firing rule of Effects §4.4.
Source code in src/quivers/stochastic/effect_lifts.py
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | |
swap_rule_set
¶
swap_rule_set(distributive_laws: tuple[object, ...]) -> tuple[SchemaDecl, ...]
Generate one swap_TU schema per registered distributive law.
The resulting tuple is appended to the chart parser's rule set alongside the class-driven lifts; the chart's commutation-firing dispatch picks each swap schema up by name.
Source code in src/quivers/stochastic/effect_lifts.py
313 314 315 316 317 318 319 320 321 322 | |
lift_rule_set
¶
lift_rule_set(base_schemas: tuple[SchemaDecl, ...], effects: tuple[object, ...]) -> tuple[SchemaDecl, ...]
Apply class_directed_lifts over a rule-set and effect-stack.
Returns the union of base schemas and all lifts produced for each (base_schema, effect) pair. The chart parser consumes the resulting tuple directly.
Source code in src/quivers/stochastic/effect_lifts.py
325 326 327 328 329 330 331 332 333 334 335 336 337 338 | |