|
|
|
|
|
by ImprobableTruth
2052 days ago
|
|
>The main challenge of refinement types is that arbitrary properties are very difficult to check in general. While this is true, I'm not sure how constructive types don't face the very same issue. Ultimately, you will have to provide evidence for the required properties, with constructive types the proof is just (more or less) implicitly embedded into the datatype, which imo just makes dealing with these properties harder rather than easier. In regards to the post by Hillel Wayne you've posted, I'm not sure what this statement >This means that predicative data is easier to express at the cost of permitting representable invalid data. This is enough of a problem that we prefer constructive data whenever feasible. is supposed to mean exactly. If your predicate makes some data invalid, it's just not representable in the refined type. |
|
Author here. It's representable; the type checker has to prove it never happens in practice. This requires very different techniques from typechecking constructive types. Liquid Haskell shells out to Z3, which can return "unknown" as an answer in addition to "sat" or "unsat".
(There's actually a fourth option, which is that Z3 runs forever, but I think LH does a bunch of clever design to avoid that case.)
You can also `assume` that refinements are satisfied without proving them, in which case they can be violated at runtime. This would be impossible if the invalid data was unrepresentable.
Other approaches to refinement types, such as the original ML paper [0], implemented them constructively and didn't have this problem.
[0]: https://www.cs.cmu.edu/~fp/papers/pldi91.pdf