ucsd-progsys / liquidhaskell

Liquid Types For Haskell

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Prove two functions are equal by extensionality

josedusol opened this issue · comments

Im reading test T1577.hs, which ilustrates the use of the --extensionality flag. For example:

{-@ reflect plus1 @-}
{-@ reflect plus1' @-}
plus1, plus1' :: Int -> Int 
plus1 x = x + 1 
plus1' x = 1 + x

{-@ thm1 :: () -> { plus1' == plus1 } @-}
thm1 :: () -> ()
thm1 _ = () 

In this case it seems the proof is discharged automatically by the SMT. However, could it be possible to explicitly write the proof in detail?
I imagine in this simple example the proof could be something like:

  ==. plus1' x
  ==. 1 + x
  ==. x + 1
  ==. plus1 x
  *** QED    

But obviously this is not matching the goal { plus1' == plus1 }.

You could, but you would need an extensionality axiom to conclude function equality.
The problem is that function equality is not an easy topic and to encode function extensionality correctly you need a type-based axiom.... https://dl.acm.org/doi/pdf/10.1145/3546189.3549919

Ah, interesting. Will take a look. Thanks

So, im playing with the extensionality axiom as is presented in the paper:

{-@ assume funext :: forall a b. f:(a -> b) -> g:(a -> b) -> (x:a -> {f x = g x}) -> {f = g} @-}
funext _f _g _pf = ()

However, LH doesn't like it:

src\Test.hs:6:22: error:
* Specified type does not refine Haskell type for Test.funext (Plugged Init types new)
The Liquid type
.
forall a b . (a -> b) -> (a -> b) -> (a -> _) -> _
.
is inconsistent with the Haskell type
.
forall p1 p2 p3 -> p1 -> p2 -> p3 -> ()
.
defined at src\Test.hs:7:1-6
.
Specifically, the Liquid component
.
lq_tmp$db##0:a -> b
.
is inconsistent with the Haskell component
.
p
.

HINT: Use the hole '_' instead of the mismatched component (in the Liquid specification)
*
|
6 | {-@ assume funext :: forall a b. f:(a -> b) -> g:(a -> b) -> (x:a -> {f x = g x}) -> {f = g} @-}

Not sure if this is just a version problem (using liquidhaskell-0.9.0.2) or im missing a directive. Besides, what is the purpose of prefixing variable names with underscores (e.g. "_f" or "_g") in proofs ?

Can you add the Haskell type of funext?

Can you add the Haskell type of funext?

Yeah, that and adding --higherorder solved the issue. Thanks