diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,131 @@
 
 ---
 
+## [0.17.5] - 2026-08-19
+
+Point release on the 0.17.x line. Two language-surface changes lead: sum-type eliminators unify on
+`match` (scrutinee-first), and the primitive set is tentatively finalized — `strings.lines`/`unlines`
+are removed in favour of `hydra.formatting` term helpers. A symlink-aware filesystem family lands
+across all ten hosts, and Hydra's own build system continues its migration into Hydra.
+
+**Backward-incompatible.** The `cases` -> `match` rename and the `strings.lines`/`unlines` removal
+both change the published kernel surface. Code written against 0.17.4 that uses `Optionals.cases`
+or `strings.lines`/`strings.unlines` must be updated.
+
+### Highlights
+
+- **Sum-type eliminators unify on `match`** ([#615](https://github.com/CategoricalData/hydra/issues/615)):
+  the `cases`/`match` helper pair is flipped to a single scrutinee-first `match` convention across the
+  Haskell, Java, Python, and Scala DSLs, the `optionals.cases` -> `optionals.match` kernel primitive,
+  and the corresponding implementations in TypeScript and all four Lisp dialects.
+- **Primitive set tentatively finalized** ([#417](https://github.com/CategoricalData/hydra/issues/417)):
+  `strings.lines` and `strings.unlines` are removed as primitives; their semantics are preserved as
+  `hydra.formatting.lines`/`unlines` term helpers, with overlay implementations dropped across all ten
+  hosts and callers repointed.
+- **Symlink-aware filesystem primitives** ([#666](https://github.com/CategoricalData/hydra/issues/666)):
+  `status(followLinks)`, `createSymlink`, and `readSymlink` land with native implementations for every
+  host — Haskell, Java, Python, Scala, TypeScript, Clojure, Common Lisp, Scheme, and Emacs Lisp.
+- **Build system promotion continues** ([#416](https://github.com/CategoricalData/hydra/issues/416)):
+  adds `hydra.build.walk` extension-glob helpers (`extensionOf`/`filterByExtension`/`matchesExtension`)
+  and `hydra.build.comparereportlogic`, a set of pure snapshot-compare decision helpers.
+
+### Bug fixes
+
+- **`math.range` was inclusive of both bounds** ([#647](https://github.com/CategoricalData/hydra/issues/647)),
+  silently fabricating an extra element in index arithmetic.
+- **Java coder TCO-`cases` codegen** dropped enclosing-method type parameters from union-variant casts
+  (found via [#666](https://github.com/CategoricalData/hydra/issues/666)).
+- **`ShaclRdf` promoted to a DSL module** ([#652](https://github.com/CategoricalData/hydra/issues/652))
+  so the SHACL pipeline works outside Haskell.
+- **Cold-seed shim portability**: the R22 bootstrap shim used GNU-only `\+` and `\b`, which fail under
+  BSD `sed` on macOS ([#417](https://github.com/CategoricalData/hydra/issues/417)).
+- **Bootstrap Haskell target missing `unix`**: the demo's static `package.yaml` was not updated when
+  `System.Posix.Files` entered the kernel overlay, breaking every `*-to-haskell` bootstrap cell
+  ([#670](https://github.com/CategoricalData/hydra/issues/670)).
+- **Bootstrap comparison scored Scala and TypeScript cells as passing without comparing anything**:
+  `compare_output`'s target switch was missing both languages, so the baseline path was malformed,
+  every file counted as "no baseline found", and a zero-file comparison reported `pass`. A Scala or
+  TypeScript *target* cell could never fail ([#671](https://github.com/CategoricalData/hydra/issues/671)).
+
+### Known issues
+
+- A pre-#630 post-generation text pass rewrites `hydra.lib.<sub>` -> `hydra.overlay.<lang>.lib.<sub>`
+  in generated **doc comments** as well as code, because its quote-prefix guard does not recognize
+  mid-sentence prose references. Affects two kernel doc strings in `src/main`
+  (`hydra.error.system`, `hydra.error.packaging`) plus ~20 generated docstrings in the test tree;
+  cosmetic only, no behavioral impact. Tracked as part of
+  [#633](https://github.com/CategoricalData/hydra/issues/633).
+- Bootstrap comparison diff detail is not persisted to the run directory
+  ([#671](https://github.com/CategoricalData/hydra/issues/671)).
+
+---
+
+## [0.17.4] - 2026-08-09
+
+Point release on the 0.17.x line. Fixes an inference bug that mis-typed generated Java and Python for
+`readFile`, adds the `divide` primitive, and restores `hydra-ext` to the published package set. Release
+validation also surfaced a family of pre-existing cross-host code-generation defects — none of which the
+per-host CI jobs can catch, because only the bootstrap exercises one host generating *another*.
+
+### Highlights
+
+- **Output-only nominal generalization fixed** ([#637](https://github.com/CategoricalData/hydra/issues/637),
+  with [#638](https://github.com/CategoricalData/hydra/issues/638) /
+  [#639](https://github.com/CategoricalData/hydra/issues/639) /
+  [#640](https://github.com/CategoricalData/hydra/issues/640)): a nominal type appearing only in the
+  *output* position of a primitive's signature was generalized to a free type variable instead of resolving
+  as nominal, mis-typing the generated Java and Python for `readFile`. Also widens universe closure and adds
+  a `kernelTypeUniverse` helper, an effect DSL builder, and `effects`/`files`/`text`/`system` lib wrappers.
+- **`divide` primitive** ([#317](https://github.com/CategoricalData/hydra/issues/317)): now present in the
+  published kernel. This also clears the cold-clone dangle, since a cold seed against published 0.17.4
+  resolves `DefMath.divide`.
+- **`hydra-ext` republished** ([#636](https://github.com/CategoricalData/hydra/issues/636)): back in the
+  published set after its absence from 0.17.1–0.17.3, shipping to Hackage and PyPI.
+
+### Bug fixes
+
+- **Overlay-lib redirection skipped for the Haskell target**
+  ([#630](https://github.com/CategoricalData/hydra/issues/630)):
+  the Java, Python, Scheme, Clojure and Common Lisp heads resolved the overlay lib directory using an
+  all-lowercase path and did not lower-case the names they scanned. Haskell's overlay tree is capitalized
+  (`Hydra/Overlay/Haskell/Lib/`), so every `hydra.lib.*` redirect silently failed and the generated Haskell
+  imported `Hydra.Lib.*` instead of `Hydra.Overlay.Haskell.Lib.*`, producing hundreds of type errors. The
+  defect was invisible on case-sensitive filesystems, where the failed directory check falls back to a
+  hard-coded list that happens to be correct. The Python head carried *two* independent copies of this scan;
+  only the one in `generation.py` feeds the Haskell coder.
+- **Lisp-as-host bootstrap** ([#520](https://github.com/CategoricalData/hydra/issues/520),
+  [#630](https://github.com/CategoricalData/hydra/issues/630)): the four Lisp head decode drivers called
+  `from_json` with a stale 4-argument signature, and the Lisp bootstrap-driver coders were not pre-bound with
+  `overlaySubs`.
+- **Python-as-host dropped the `Graph` argument** ([#630](https://github.com/CategoricalData/hydra/issues/630)):
+  `overlaySubs` was not threaded into the Python head's `write_*` wrappers.
+- **Clojure `resolve-coder` and `decimal-to-float32`**
+  ([#630](https://github.com/CategoricalData/hydra/issues/630)): a stray parenthesis closed a `case` early,
+  making an unsupported-default block run unconditionally; and `(float (.doubleValue ...))` threw on
+  `Float.MAX_VALUE`, now saturating via `(.floatValue (bigdec x))`.
+- **Cold-seeder failed on macOS** ([#630](https://github.com/CategoricalData/hydra/issues/630)): the #376
+  cold seeder used a bare `sed -i -e`, which is GNU-only and aborts immediately under BSD `sed`.
+
+### Release engineering
+
+- **Review checkpoint before Maven Central publishes**
+  ([#591](https://github.com/CategoricalData/hydra/issues/591)): `HYDRA_JAVA_PUBLISH_HOLD=1` uploads the
+  aggregated Java deployment as `USER_MANAGED`, so it validates and then holds for review instead of
+  publishing automatically. This mirrors `HYDRA_SCALA_PUBLISH_HOLD` and makes an upload reversible — a held
+  deployment can be dropped, whereas an automatic one cannot be undone.
+
+### Known issues
+
+- **`hydra-ext` is not published to Maven Central**
+  ([#643](https://github.com/CategoricalData/hydra/issues/643)): it does not compile for the Java target,
+  because the visitor-pattern inner interface the Java coder emits collides with the enclosing `Visitor`
+  type in `hydra.cpp.syntax`. Only Java is affected; the Python coder emits sibling classes rather than
+  nested ones. ext ships to Hackage and PyPI at 0.17.4 and is expected to rejoin the Java set once fixed.
+- **TypeScript no longer self-hosts**
+  ([#642](https://github.com/CategoricalData/hydra/issues/642)): the TypeScript host's JSON decoder fails to
+  decode most of the kernel, so `typescript-as-host` code generation is broken. No published artifact is
+  affected — `dist/typescript` is generated by the Haskell host and passes its test suite.
+
 ## [0.17.3] - 2026-08-01
 
 Point release on the 0.17.x line, focused on **release-artifact integrity**. The 0.17.2 release shipped
diff --git a/hydra-scala.cabal b/hydra-scala.cabal
--- a/hydra-scala.cabal
+++ b/hydra-scala.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.39.1.
+-- This file has been generated from package.yaml by hpack version 0.38.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           hydra-scala
-version:        0.17.4
+version:        0.17.5
 synopsis:       Hydra's Scala coder: emit Scala source from Hydra modules
 description:    Hydra is an implementation of the LambdaGraph data model, which takes advantage of an isomorphism between labeled hypergraphs and typed lambda calculus: in Hydra, "graphs are programs, and programs are graphs". Scala support for Hydra
 category:       Data
@@ -40,7 +40,7 @@
   build-depends:
       base >=4.19.0 && <4.22
     , containers >=0.6.7 && <0.8
-    , hydra-jvm ==0.17.4
-    , hydra-kernel ==0.17.4
+    , hydra-jvm ==0.17.5
+    , hydra-kernel ==0.17.5
     , scientific >=0.3.7 && <0.4
   default-language: Haskell2010
diff --git a/src/main/haskell/Hydra/Dsl/Scala/Syntax.hs b/src/main/haskell/Hydra/Dsl/Scala/Syntax.hs
--- a/src/main/haskell/Hydra/Dsl/Scala/Syntax.hs
+++ b/src/main/haskell/Hydra/Dsl/Scala/Syntax.hs
@@ -7,7 +7,7 @@
 import qualified Hydra.Core as Core
 import qualified Hydra.Scala.Syntax as Syntax
 import qualified Hydra.Typed as Typed
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Int as I
 
diff --git a/src/main/haskell/Hydra/Scala/Coder.hs b/src/main/haskell/Hydra/Scala/Coder.hs
--- a/src/main/haskell/Hydra/Scala/Coder.hs
+++ b/src/main/haskell/Hydra/Scala/Coder.hs
@@ -66,7 +66,7 @@
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variables as Variables
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Map as M
 import qualified Data.Set as S
@@ -128,7 +128,7 @@
 -- | Filter/rewrite a raw type-application list against callee-scheme over-generalization (#589)
 correctTypeApps :: Core.Name -> [Core.Type] -> Graph.Graph -> Either t0 [Core.Type]
 correctTypeApps name fallbackTypeApps g =
-    Optionals.cases (Lexical.lookupBinding g name) (Right fallbackTypeApps) (\el -> Optionals.cases (Core.bindingTypeScheme el) (Right fallbackTypeApps) (\ts ->
+    Optionals.match (Lexical.lookupBinding g name) (Right fallbackTypeApps) (\el -> Optionals.match (Core.bindingTypeScheme el) (Right fallbackTypeApps) (\ts ->
       let schemeType = Core.typeSchemeBody ts
           allSchemeVars = Lists.filter (\vv -> isSimpleName vv) (Core.typeSchemeVariables ts)
           schemeTypeVars = collectTypeVars schemeType
@@ -172,10 +172,10 @@
                     _ -> Nothing
           directRefSubst = directRefSubstitution directInputVars codVar groupedDirect
           codSubst =
-                  Optionals.cases (findPairFirst cod) Maps.empty (\cv -> Logic.ifElse (Maps.member cv selfRefSubst) Maps.empty (Optionals.cases (findSelfRefVar groupedByInput) Maps.empty (\refVar -> Logic.ifElse (Equality.equal cv refVar) Maps.empty (Maps.singleton cv refVar))))
+                  Optionals.match (findPairFirst cod) Maps.empty (\cv -> Logic.ifElse (Maps.member cv selfRefSubst) Maps.empty (Optionals.match (findSelfRefVar groupedByInput) Maps.empty (\refVar -> Logic.ifElse (Equality.equal cv refVar) Maps.empty (Maps.singleton cv refVar))))
           domVars = Sets.fromList (Lists.bind doms (\d -> Sets.toList (collectTypeVars d)))
           danglingSubst =
-                  Optionals.cases (findPairFirst cod) Maps.empty (\cv -> Logic.ifElse (Sets.member cv domVars) Maps.empty (Optionals.cases (findSelfRefVar groupedByInput) Maps.empty (\refVar -> Maps.singleton cv (Core.TypeVariable refVar))))
+                  Optionals.match (findPairFirst cod) Maps.empty (\cv -> Logic.ifElse (Sets.member cv domVars) Maps.empty (Optionals.match (findSelfRefVar groupedByInput) Maps.empty (\refVar -> Maps.singleton cv (Core.TypeVariable refVar))))
       in (Maps.union (Maps.union (Maps.union (nameMapToTypeMap selfRefSubst) (nameMapToTypeMap codSubst)) danglingSubst) (nameMapToTypeMap directRefSubst))
 
 -- | Compute the direct-return substitution over grouped accumulator pairs (#589)
@@ -208,11 +208,11 @@
       let fname = Core.caseAlternativeName f
           fterm = Core.caseAlternativeHandler f
           isUnit =
-                  Optionals.cases (Maps.lookup fname ftypes) (case (Strip.deannotateAndDetypeTerm fterm) of
+                  Optionals.match (Maps.lookup fname ftypes) (case (Strip.deannotateAndDetypeTerm fterm) of
                     Core.TermLambda v0 ->
                       let lamParam = Core.lambdaParameter v0
                           lamBody = Core.lambdaBody v0
-                          domIsUnit = Optionals.cases (Core.lambdaDomain v0) False (\dom -> Equality.equal dom Core.TypeUnit)
+                          domIsUnit = Optionals.match (Core.lambdaDomain v0) False (\dom -> Equality.equal dom Core.TypeUnit)
                           bodyIgnoresParam = Variables.isFreeVariableInTerm lamParam lamBody
                       in (Logic.or domIsUnit bodyIgnoresParam)
                     Core.TermRecord v0 -> Equality.equal (Lists.length (Core.recordFields v0)) 0
@@ -221,7 +221,7 @@
                     Core.TypeUnit -> True
                     Core.TypeRecord v0 -> Equality.equal (Lists.length v0) 0
                     _ -> False)
-          shortTypeName = Optionals.withDefault "x" (Lists.last (Strings.splitOn "." (Optionals.cases sn "x" (\n -> Core.unName n))))
+          shortTypeName = Optionals.withDefault "x" (Lists.last (Strings.splitOn "." (Optionals.match sn "x" (\n -> Core.unName n))))
           lamParamSuffix =
                   case (Strip.deannotateAndDetypeTerm fterm) of
                     Core.TermLambda v0 ->
@@ -238,7 +238,7 @@
                     lamParamSuffix])
           domainIsUnit =
                   case (Strip.deannotateAndDetypeTerm fterm) of
-                    Core.TermLambda v0 -> Optionals.cases (Core.lambdaDomain v0) True (\dom -> Equality.equal dom Core.TypeUnit)
+                    Core.TermLambda v0 -> Optionals.match (Core.lambdaDomain v0) True (\dom -> Equality.equal dom Core.TypeUnit)
                     _ -> True
           patArgs = Logic.ifElse isUnit (Logic.ifElse domainIsUnit [] [
                 Syntax.PatWildcard]) [
@@ -312,13 +312,13 @@
                                   Sets.fromList (Lists.filter (\n -> Logic.not (Lists.member 46 (Strings.toList (Core.unName n)))) (Sets.toList freeVars))
                           unresolvedVars = Sets.difference unqualifiedFreeVars (Graph.graphTypeVariables g)
                       in (Logic.ifElse (Sets.null unresolvedVars) (Just dom) Nothing))
-        in (Eithers.bind (encodeTerm overlaySubs cx g body) (\sbody -> Eithers.bind (Optionals.cases mdom (findSdom cx g meta) (\dom -> Eithers.bind (encodeType cx g dom) (\sdom -> Right (Just sdom)))) (\sdom -> Right (Utils.slambda v sbody sdom))))
-      Core.TermUnwrap _ -> Optionals.cases arg (Eithers.bind (findSdom cx g meta) (\sdom -> Right (Utils.slambda "x" (Utils.sname "x") sdom))) (\a -> encodeTerm overlaySubs cx g a)
+        in (Eithers.bind (encodeTerm overlaySubs cx g body) (\sbody -> Eithers.bind (Optionals.match mdom (findSdom cx g meta) (\dom -> Eithers.bind (encodeType cx g dom) (\sdom -> Right (Just sdom)))) (\sdom -> Right (Utils.slambda v sbody sdom))))
+      Core.TermUnwrap _ -> Optionals.match arg (Eithers.bind (findSdom cx g meta) (\sdom -> Right (Utils.slambda "x" (Utils.sname "x") sdom))) (\a -> encodeTerm overlaySubs cx g a)
       Core.TermProject v0 ->
         let fname = Utils.scalaEscapeName (Core.unName (Core.projectionFieldName v0))
             typeName = Core.projectionTypeName v0
             pv = "x"
-        in (Optionals.cases arg (Eithers.bind (Eithers.either (\_ -> Right Nothing) (\msdom -> Right msdom) (findSdom cx g meta)) (\msdom -> Right (Utils.slambda pv (Syntax.DataRef (Syntax.RefDataSelect (Syntax.SelectData {
+        in (Optionals.match arg (Eithers.bind (Eithers.either (\_ -> Right Nothing) (\msdom -> Right msdom) (findSdom cx g meta)) (\msdom -> Right (Utils.slambda pv (Syntax.DataRef (Syntax.RefDataSelect (Syntax.SelectData {
           Syntax.selectDataQual = (Utils.sname pv),
           Syntax.selectDataName = Syntax.NameData {
             Syntax.nameDataValue = (Syntax.PredefString fname)}}))) msdom))) (\a -> Eithers.bind (encodeTerm overlaySubs cx g a) (\sa -> Right (Syntax.DataRef (Syntax.RefDataSelect (Syntax.SelectData {
@@ -333,11 +333,11 @@
             cases = Core.caseStatementCases v0
             dflt = Core.caseStatementDefault v0
             ftypes = Eithers.either (\_ -> Maps.empty) (\x_ -> x_) (Resolution.fieldTypes cx g dom)
-        in (Eithers.bind (Eithers.mapList (\f -> encodeCase overlaySubs cx g ftypes sn f) cases) (\fieldCases -> Eithers.bind (Optionals.cases dflt (Right fieldCases) (\dfltTerm -> Eithers.bind (encodeTerm overlaySubs cx g dfltTerm) (\sdflt -> Right (Lists.concat2 fieldCases [
+        in (Eithers.bind (Eithers.mapList (\f -> encodeCase overlaySubs cx g ftypes sn f) cases) (\fieldCases -> Eithers.bind (Optionals.match dflt (Right fieldCases) (\dfltTerm -> Eithers.bind (encodeTerm overlaySubs cx g dfltTerm) (\sdflt -> Right (Lists.concat2 fieldCases [
           Syntax.Case {
             Syntax.casePat = Syntax.PatWildcard,
             Syntax.caseCond = Nothing,
-            Syntax.caseBody = sdflt}])))) (\scases -> Optionals.cases arg (Eithers.bind (findSdom cx g meta) (\sdom -> Right (Utils.slambda v (Syntax.DataMatch (Syntax.MatchData {
+            Syntax.caseBody = sdflt}])))) (\scases -> Optionals.match arg (Eithers.bind (findSdom cx g meta) (\sdom -> Right (Utils.slambda v (Syntax.DataMatch (Syntax.MatchData {
           Syntax.matchDataExpr = (Utils.sname v),
           Syntax.matchDataCases = scases})) sdom))) (\a -> Eithers.bind (encodeTerm overlaySubs cx g a) (\sa -> Right (Syntax.DataMatch (Syntax.MatchData {
           Syntax.matchDataExpr = sa,
@@ -350,15 +350,15 @@
 
       let bname = Utils.scalaEscapeName (Core.unName (Core.bindingName b))
           bterm = Core.bindingTerm b
-          mts = Optionals.cases (Core.bindingTypeScheme b) (Maps.lookup (Core.bindingName b) (Graph.graphBoundTypes g)) (\ts -> Just ts)
+          mts = Optionals.match (Core.bindingTypeScheme b) (Maps.lookup (Core.bindingName b) (Graph.graphBoundTypes g)) (\ts -> Just ts)
           isFn =
-                  Optionals.cases mts False (\ts -> case (Strip.deannotateType (Core.typeSchemeBody ts)) of
+                  Optionals.match mts False (\ts -> case (Strip.deannotateType (Core.typeSchemeBody ts)) of
                     Core.TypeFunction _ -> True
                     Core.TypeForall v0 -> case (Strip.deannotateType (Core.forallTypeBody v0)) of
                       Core.TypeFunction _ -> True
                       _ -> False
                     _ -> False)
-      in (Optionals.cases mts (Eithers.bind (encodeTerm overlaySubs cx g bterm) (\srhs -> Right (Syntax.StatDefn (Syntax.DefnVal (Syntax.ValDefn {
+      in (Optionals.match mts (Eithers.bind (encodeTerm overlaySubs cx g bterm) (\srhs -> Right (Syntax.StatDefn (Syntax.DefnVal (Syntax.ValDefn {
         Syntax.valDefnMods = [
           Syntax.ModLazy],
         Syntax.valDefnPats = [
@@ -475,7 +475,7 @@
             Core.TermProject _ -> encodeTerm overlaySubs cx g substitutedBody
             Core.TermCases _ -> encodeTerm overlaySubs cx g substitutedBody
             Core.TermUnwrap _ -> encodeTerm overlaySubs cx g substitutedBody
-            Core.TermVariable v1 -> Eithers.bind (correctTypeApps v1 typeArgs g) (\correctedTypeArgs -> Eithers.bind (Eithers.mapList (\targ -> encodeType cx g targ) correctedTypeArgs) (\stypeArgs -> Optionals.cases (Maps.lookup v1 (Graph.graphPrimitives g)) (Eithers.bind (encodeTerm overlaySubs cx g substitutedBody) (\svar -> Right (Utils.sapplyTypes svar stypeArgs))) (\_prim -> Right (Utils.sapplyTypes (Utils.sprim overlaySubs v1) stypeArgs))))
+            Core.TermVariable v1 -> Eithers.bind (correctTypeApps v1 typeArgs g) (\correctedTypeArgs -> Eithers.bind (Eithers.mapList (\targ -> encodeType cx g targ) correctedTypeArgs) (\stypeArgs -> Optionals.match (Maps.lookup v1 (Graph.graphPrimitives g)) (Eithers.bind (encodeTerm overlaySubs cx g substitutedBody) (\svar -> Right (Utils.sapplyTypes svar stypeArgs))) (\_prim -> Right (Utils.sapplyTypes (Utils.sprim overlaySubs v1) stypeArgs))))
             _ -> encodeTerm overlaySubs cx g substitutedBody
         Core.TermTypeLambda v0 -> encodeTerm overlaySubs cx (Scoping.extendGraphForTypeLambda g v0) (Core.typeLambdaBody v0)
         Core.TermApplication v0 ->
@@ -521,7 +521,7 @@
             _ -> Right litData)
         Core.TermMap v0 -> Eithers.bind (Eithers.mapList (\kv -> Eithers.bind (encodeTerm overlaySubs cx g (Pairs.first kv)) (\sk -> Eithers.bind (encodeTerm overlaySubs cx g (Pairs.second kv)) (\sv -> Right (Utils.sassign sk sv)))) (Maps.toList v0)) (\spairs -> Right (Utils.sapply (Utils.sname "Map") spairs))
         Core.TermWrap v0 -> encodeTerm overlaySubs cx g (Core.wrappedTermBody v0)
-        Core.TermOptional v0 -> Optionals.cases v0 (Right (Utils.sname "None")) (\t -> Eithers.bind (encodeTerm overlaySubs cx g t) (\s -> Right (Utils.sapply (Utils.sname "Some") [
+        Core.TermOptional v0 -> Optionals.match v0 (Right (Utils.sname "None")) (\t -> Eithers.bind (encodeTerm overlaySubs cx g t) (\s -> Right (Utils.sapply (Utils.sname "Some") [
           s])))
         Core.TermRecord v0 ->
           let rname = Core.recordTypeName v0
@@ -535,7 +535,7 @@
               ft = Core.fieldTerm (Core.injectionField v0)
               lhs = Utils.sname (Utils.qualifyUnionFieldName "UNION." (Just sn) fn)
               unionFtypes = Eithers.either (\_ -> Maps.empty) (\x_ -> x_) (Resolution.fieldTypes cx g (Core.TypeVariable sn))
-          in (Logic.ifElse (Optionals.cases (Maps.lookup fn unionFtypes) (case (Strip.deannotateAndDetypeTerm ft) of
+          in (Logic.ifElse (Optionals.match (Maps.lookup fn unionFtypes) (case (Strip.deannotateAndDetypeTerm ft) of
             Core.TermUnit -> True
             Core.TermRecord v1 -> Equality.equal (Lists.length (Core.recordFields v1)) 0
             _ -> False) (\dom -> case (Strip.deannotateType dom) of
@@ -543,7 +543,7 @@
             Core.TypeRecord v1 -> Equality.equal (Lists.length v1) 0
             _ -> False)) (Right lhs) (Eithers.bind (encodeTerm overlaySubs cx g ft) (\sarg -> Right (Utils.sapply lhs [
             sarg]))))
-        Core.TermVariable v0 -> Optionals.cases (Maps.lookup v0 (Graph.graphPrimitives g)) (
+        Core.TermVariable v0 -> Optionals.match (Maps.lookup v0 (Graph.graphPrimitives g)) (
           let fullName = Core.unName v0
               localName = Names.localNameOf v0
               parts = Strings.splitOn "." fullName
@@ -578,7 +578,7 @@
           term = Packaging.termDefinitionBody td
           lname = Utils.scalaEscapeName (Names.localNameOf name)
           typ_ =
-                  Optionals.cases (Optionals.map Scoping.termSignatureToTypeScheme (Packaging.termDefinitionSignature td)) (Core.TypeVariable (Core.Name "hydra.core.Unit")) Core.typeSchemeBody
+                  Optionals.match (Optionals.map Scoping.termSignatureToTypeScheme (Packaging.termDefinitionSignature td)) (Core.TypeVariable (Core.Name "hydra.core.Unit")) Core.typeSchemeBody
           isFunctionType =
                   case (Strip.deannotateType typ_) of
                     Core.TypeFunction _ -> True
@@ -1004,7 +1004,7 @@
 -- | Find the domain type from annotations
 findDomain :: t0 -> Graph.Graph -> M.Map Core.Name Core.Term -> Either Errors.Error Core.Type
 findDomain cx g meta =
-    Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g meta)) (\r -> Optionals.cases r (Left (Errors.ErrorOther (Errors.OtherError "expected a typed term"))) (\t -> case (Strip.deannotateType t) of
+    Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g meta)) (\r -> Optionals.match r (Left (Errors.ErrorOther (Errors.OtherError "expected a typed term"))) (\t -> case (Strip.deannotateType t) of
       Core.TypeFunction v0 -> Right (Core.functionTypeDomain v0)
       _ -> Left (Errors.ErrorOther (Errors.OtherError "expected a function type"))))
 
@@ -1027,7 +1027,7 @@
 -- | Find the Scala domain type for a function from annotations
 findSdom :: t0 -> Graph.Graph -> M.Map Core.Name Core.Term -> Either Errors.Error (Maybe Syntax.Type)
 findSdom cx g meta =
-    Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g meta)) (\mtyp -> Optionals.cases mtyp (Right Nothing) (\t -> case (Strip.deannotateType t) of
+    Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g meta)) (\mtyp -> Optionals.match mtyp (Right Nothing) (\t -> case (Strip.deannotateType t) of
       Core.TypeFunction v0 ->
         let dom = Core.functionTypeDomain v0
         in (Eithers.bind (encodeType cx g dom) (\sdom -> Right (Just sdom)))
@@ -1051,7 +1051,7 @@
     Lists.foldl (\m -> \p ->
       let k = Pairs.first p
           vv = Pairs.second p
-      in (Maps.alter (\mv -> Optionals.cases mv (Just (Lists.singleton vv)) (\vs -> Just (Lists.concat2 vs (Lists.singleton vv)))) k m)) Maps.empty pairs
+      in (Maps.alter (\mv -> Optionals.match mv (Just (Lists.singleton vv)) (\vs -> Just (Lists.concat2 vs (Lists.singleton vv)))) k m)) Maps.empty pairs
 
 -- | True if a type-variable name has no namespace qualifier (#589)
 isSimpleName :: Core.Name -> Bool
@@ -1115,7 +1115,7 @@
 substituteTypeVarsWithTypesGo :: M.Map Core.Name Core.Type -> Core.Type -> Core.Type
 substituteTypeVarsWithTypesGo subst t =
     case (Strip.deannotateType t) of
-      Core.TypeVariable v0 -> Optionals.cases (Maps.lookup v0 subst) t (\rep -> rep)
+      Core.TypeVariable v0 -> Optionals.match (Maps.lookup v0 subst) t (\rep -> rep)
       Core.TypeFunction v0 -> Core.TypeFunction (Core.FunctionType {
         Core.functionTypeDomain = (substituteTypeVarsWithTypesGo subst (Core.functionTypeDomain v0)),
         Core.functionTypeCodomain = (substituteTypeVarsWithTypesGo subst (Core.functionTypeCodomain v0))})
diff --git a/src/main/haskell/Hydra/Scala/Language.hs b/src/main/haskell/Hydra/Scala/Language.hs
--- a/src/main/haskell/Hydra/Scala/Language.hs
+++ b/src/main/haskell/Hydra/Scala/Language.hs
@@ -35,7 +35,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Set as S
 
diff --git a/src/main/haskell/Hydra/Scala/Serde.hs b/src/main/haskell/Hydra/Scala/Serde.hs
--- a/src/main/haskell/Hydra/Scala/Serde.hs
+++ b/src/main/haskell/Hydra/Scala/Serde.hs
@@ -43,7 +43,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 
 -- | Convert a case clause to an expression
@@ -166,7 +166,7 @@
                                 Syntax.PatVar v1 -> Syntax.varPatName v1
                       in (Syntax.unPredefString (Syntax.nameDataValue patName))) (Lists.head pats))
             nameAndType =
-                    Optionals.cases typ (Serialization.cst nameStr) (\t -> Serialization.spaceSep [
+                    Optionals.match typ (Serialization.cst nameStr) (\t -> Serialization.spaceSep [
                       Serialization.cst (Strings.concat2 nameStr ":"),
                       (typeToExpr t)])
             valKeyword = Logic.ifElse (Lists.null mods) "val" "lazy val"
diff --git a/src/main/haskell/Hydra/Scala/Syntax.hs b/src/main/haskell/Hydra/Scala/Syntax.hs
--- a/src/main/haskell/Hydra/Scala/Syntax.hs
+++ b/src/main/haskell/Hydra/Scala/Syntax.hs
@@ -5,7 +5,7 @@
 module Hydra.Scala.Syntax where
 
 import qualified Hydra.Core as Core
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Int as I
 
diff --git a/src/main/haskell/Hydra/Scala/Utils.hs b/src/main/haskell/Hydra/Scala/Utils.hs
--- a/src/main/haskell/Hydra/Scala/Utils.hs
+++ b/src/main/haskell/Hydra/Scala/Utils.hs
@@ -45,7 +45,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Set as S
 
@@ -60,7 +60,7 @@
 -- | Qualify a union field name, optionally prefixing with the Scala type name
 qualifyUnionFieldName :: String -> Maybe Core.Name -> Core.Name -> String
 qualifyUnionFieldName dlft sname fname =
-    Strings.concat2 (Optionals.cases sname dlft (\n -> Strings.concat2 (scalaTypeName True n) ".")) (scalaEscapeName (Core.unName fname))
+    Strings.concat2 (Optionals.match sname dlft (\n -> Strings.concat2 (scalaTypeName True n) ".")) (scalaEscapeName (Core.unName fname))
 
 -- | Apply a Scala data expression to a list of arguments
 sapply :: Syntax.Data -> [Syntax.Data] -> Syntax.Data
