4 questions to test your understanding
A function is declared with liquid type `incr :: x:{Int | x >= 0} -> {y:Int | y > x}`. What does the type checker verify when this function is called with argument 5?
Liquid types restrict refinement predicates to a decidable fragment (typically quantifier-free linear arithmetic). Why not allow arbitrary logic like full first-order logic?
Liquid Haskell verifies a function `divide :: x:Nat -> y:{Nat | y != 0} -> Nat`. When type-checking a call `divide(10, 0)`, what happens?
Consider a function `sum :: xs:[Int]<{v:Int | v > 0}> -> {n:Int | n > 0}` that sums a non-empty list of positive integers. How would a liquid type checker verify this?