Liquid PureScript · lps Refinement types · external tool · Z3

Verdicts

The whole golden table, current.

This is test/golden.txt — every function in the example corpus, run on every build. SAFE and UNSAFE cases in near-equal measure, on purpose: a verifier that says SAFE to everything must fail loudly here. The four modules escalate — basics, composition, inductive data, arrays.

22SAFE
4UNSAFE — with counterexample
1UNSUPPORTED — deliberate mismatch
4Modules

Demo

basics + counterexamples · Demo.purs / Demo.lps
absSafeBoth branches land in Nat.
signSafeGuards + otherwise; result stays in [-1, 1].
doubleSafelet m = n + n — the bind enters the context as an equality.
clampSafeDependent spec across binders: result in [lo, hi].
lowSafemin n 0 <= 0 — discharged once the corpus supplies min's spec.
flagSafeBoolean-result refinement: returns true when n >= 0.
badUnsafebad n = n - 1 is not always >= 0. at Demo.purs:9:9 · counterexample: n = 0
onceUnsupportedDeliberate spec/type mismatch — the spec declares 2 arguments, the type has 1. Caught by the docs.json cross-check before solving.

P1

compositional — call sites, recursion, assume · P1.purs / P1.lps
myAbsSafeThe reusable Nat-returning absolute value.
distSafeCalls myAbs; its postcondition is assumed at the site.
sumToSafeRecursion — the recursive call assumes sumTo's own spec.
incSafePrecondition n >= 0 ⇒ result >= 1.
callGoodSafeinc (myAbs n)myAbs's postcondition discharges inc's precondition.
low2Safemin n 0 <= 0, via the trusted min spec.
sizeSafeMulti-alternative case on Int literals; result in [0, 2].
callBadUnsafeinc n without myAbsn may be negative, so inc's precondition fails at the call site. at P1.purs:21:13 · counterexample: n = -1

P2

inductive ADTs via measures · P2.purs / P2.lps
countSafeProves count l == len l by induction (own-spec recursion).
appendSafeProves len (append a b) == len a + len b via constructor facts.
singletonSafelen (ICons x INil) == 1 through nested constructor applications.
headOrSafeTotal head — the INil case supplies the default.
badCountUnsafeForgets the + 1, so the count can't equal len l. at P2.purs:21:16 · counterexample: a non-empty list — the dropped step makes the count disagree with the measure

Arrays

built-in length measure + library specs · Arrays.purs / Arrays.lps
threeSafe[1,2,3] has length exactly 3 — literals contribute exact lengths.
growSafecons 0 xs — length grows by one.
midSafeValid index via Euclidean division, under a non-empty precondition.
firstHalfSafetake (length xs / 2) xs — result no longer than xs.
restSafedrop 1 off a non-empty array — length is exactly one less.
badMidUnsafeSame body as mid but without the non-empty precondition: badMid [] = 0 is not < length []. at Arrays.purs:18:13 · counterexample: xs = []

Why the failures are the point. Each UNSAFE case is a working function that would compile and run — it's the refinement it fails, and the tool pins the failing span and hands back an input that breaks it. once, the lone UNSUPPORTED, is a spec that has drifted from its type; the tool refuses to solve rather than guess. Nothing here is a silent pass.