Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow refinements in the output type of measures #126

Closed
gridaphobe opened this issue Sep 24, 2013 · 12 comments
Closed

Allow refinements in the output type of measures #126

gridaphobe opened this issue Sep 24, 2013 · 12 comments

Comments

@gridaphobe
Copy link
Contributor

Only base types are allowed to appear in the type of a measure, but this is less accurate than it could be, e.g. when dealing with measures that denote the size of a value.

measure len :: [a] -> Int
len []     = 0
len (x:xs) = 1 + len xs

Since the type only specifies that len returns an Int, we need to additionally define an invariant on Int.

invariant {v:[a] | (len v) >= 0}

This is a bit tedious when what we really want to write is just

measure len :: [a] -> Nat
len []     = 0
len (x:xs) = 1 + len xs

Perhaps there's a good reason to disallow refinements in the return type of a measure, but it isn't apparent to me.

@nikivazou
Copy link
Member

I believe that the invariant is basically needed to get the qualifiers,
with the correct qualifiers liquidHaskell CAN infer that len v >=0 by lenis definition.

@ranjitjhala
Copy link
Member

No it is not just for qualifiers.

The non negativity of Len can only be inferred for lists that are constructed from scratch.

Try to prove that haskell's 'drop' function returns a list with nonneg Len.
Now you will see you need that the INPUT also has non neg Len. It is to avoid writing such tedious things in the input that we need invariants.

At any rate @gridaphobe is right. It would be nice to put the fact right in the measure. Mind you we will still need the. Invariant mechanism for other things...

On Sep 25, 2013, at 8:15 AM, Niki Vazou [email protected] wrote:

I believe that the invariant is basically needed to get the qualifiers,
with the correct qualifiers liquidHaskell CAN infer that len v >=0 by lenis definition.


Reply to this email directly or view it on GitHub.

@ranjitjhala
Copy link
Member

Btw, given @nikivazou's recent progress with promoting functions to measures, it would be nice to fix the above, thereby unifying measures and invariants.

So we should be able to write:

{-@ measure len @-}
{-@ len :: [a] -> Nat @-}
len :: [a] -> Int
len []     = 0
len (x:xs) = 1 + len xs

and from that, automatically derive

invariant {v: [a] | 0 <= len v}

How? Well, suppose you have a measure from some type T to a base type B with refinement p

meas :: T -> {v:B | p}

Then you have effectively specified (and verified)

invariant {v:T | p[(meas v) / v]}

@gridaphobe
Copy link
Contributor Author

Yes, this sounds like a nice and simple approach.

I suppose in this approach, the measure-promotion would automatically refine the type of len-the-haskell-function to refer to len-the-measure? Or is @nikivazou already doing that?

Another question, should we allow promotion of functions with pre-conditions?

@nikivazou
Copy link
Member

@ranjitjhala, this is a nice (and sound) suggestion. If we support this we can stop supporting invariants (that can lead to unsoundness).

@gridaphobe we should allows promotion of functions with preconditions, but we should translate the preconditions into the types of the data constructors. (I already relate the len-the-haskell-function with len-the-measure.)

Another suggestion: since we are already becoming a "lightweight" dependent type language, how about a flag "--autopromote" that automatically promotes to logic all the appropriate functions?

@ranjitjhala
Copy link
Member

Hey, is this still open? I thought @nikivazou implemented it?

@nikivazou
Copy link
Member

It is implemented for Haskell defined measures!

@gridaphobe
Copy link
Contributor Author

@nikivazou what about for old-style measures? Not all measures can be defined in Haskell, e.g. uninterpreted measures.

@nikivazou
Copy link
Member

Curently, there is no support for invariants over old style measures.

@ranjitjhala
Copy link
Member

ranjitjhala commented Mar 20, 2017 via email

@gridaphobe
Copy link
Contributor Author

gridaphobe commented Mar 20, 2017 via email

@nikivazou
Copy link
Member

Agree, but abstract measure is just an uninterpreted function. Would need to clarify all these definitions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants