Hacker Newsnew | past | comments | ask | show | jobs | submit | richard_fey's commentslogin

How do you define operations on these liquid types? You can't even define subtraction or addition on this "non zero integer type". These types are not closed so how is it useful?


Liquid types are represented under the hood using ordinary data types, so e.g. the nonzero integer type will be stored as a value of ordinary Haskell integer type at runtime. Subtraction on the underlying type is defined as usual.

Now, the Liquid Haskell type checker knows a lot about integers: it can deduce whether your invocation of x-y could give a negative result or not.

If it cannot result in a negative value (e.g. because y has a particular liquid type), the type checker will accept your program, and you'll be able to use the subtraction function as you normally would.

However, if your invocation of x-y could potentially result in a negative value (e.g. because the values of x,y are not sufficiently constrained), the type checker will reject your program, and tell you to do something else (e.g. add runtime checks that rule out a negative result before invoking the subtraction).


Presumably it will reject it with a helpful message like "no"?

I think that's the main disadvantage of these types. It's now no longer a decidable system with (usually) easy to understand error messages. You're in the realm of formal verification and SMT solvers where the only error message is "didn't work; try something else".

Probably still good but I think it's important to be aware of the downsides.


Yes, that was my first thought.

As long as there's a good way to map from the real world into the liquid typed world, either by just telling the liquid typed world that this value can only be a positive integer, or by the liquid typed world having functions that ensure this at the boundary and return nice errors on runtime failure of this check, then it sounds really interesting.


Addition isn't a problem, any nonzero integer plus a nonzero integer is a nonzero integer.

For subtraction it becomes fallible. You get back an option, 5 - 4 = Some(1), 4 - 5 = None. (These are probably methods rather than infix operators, your language may vary.)

See for example the methods documented here: https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize...

As for it's utility, it enables certain optimizations and it can be a useful constraint. Eg for ensuring that you don't divide or multiply by zero.


It is worth pointing out that the same problems apply to "normal" integer types like int32/uint32; you can trivially over/underflow the bounds with basic arithmetic. In that sense it doesn't really matter what the bounds are exactly.


> any nonzero integer plus a nonzero integer is a nonzero integer

That’s not true. 5 + (-5) is 0.


You're right, I was thinking of a nonzero unsigned integer. D'oh! Thanks for the correction!


It would be in interred ring to have a memory bounds for the program too!


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: