To run Liquid Haskell on your Refinements.lhs file
Here: Press Play
Locally:
cabal install liquidhaskell
liquid Foo.lhs
The input x might be 0.
Fixes:
Divide with a provably non-zero value (e.g., x*x+1)
Make divx only accept non-zero arguments.
Now you can only call divx on non-zero inputs!
Q: Change the code to only call divx on non-zero.
Q: What if the call to div in divx changes?
Refinements of Haskell types with logical predicates!
{-@ divx :: x:{Int | x /= 0} -> Int @-}
The special comments {-@ ... @-} are
interpreted by Liquid Haskell, but
ignored by ghc.
Another check: head on only non-empty lists.
Q: Can you fix the error?
Fixes:
Make the list (provably) nonempty
Better, refine the type to only accept nonempty lists!
The type is good, but too restrictive.
Q: Can you make the below pass?
Q: Can you fix the type error?
{-@ div :: Int -> x:{Int | 0 /= x } -> Int @-}
{-@ head :: xs:{[a] | 0 < len xs } -> a @-}
Where do these constraints come from?
Hard-coded in Liquid Haskell or
user specified refinement types.
take?Q: Can you fix the error?
Reminder of Haskell Heartbleed.
λ> :m +Data.Text Data.Text.Unsafe
λ> takeWord16 10 (pack "zurihac")
"zurihac\NUL\26984\1930"
Detect Heartbleed with Liquid Haskell.
Text{-@ takeWord16 :: i:Nat -> xs:{Text | i < tlen xs } -> Text @-}
Define logical functions as measures.
Refinement Types: Haskell Types + Predicates
Used to:
Catch runtime crashing.
Propagate & discharge constraints.
Remove runtime checks (make unsafe functions safe!).
Other checked properties: Totality & Termination