I am having troubles proving the following law with LiquidHaskell:
It is known as (one of) DeMorgan's law, and simply states that the negation of oring two values must be the same as anding the negation of each. It's been proven for a long time, and is an example in LiquidHaskell's tutorial. I am following along in the tutorial, but fail to get the following code to pass:
-- Test.hs
module Main where
main :: IO ()
main = return ()
(==>) :: Bool -> Bool -> Bool
False ==> False = True
False ==> True  = True
True  ==> True  = True
True  ==> False = False
(<=>)  :: Bool -> Bool -> Bool
False <=> False = True
False <=> True  = False
True  <=> True  = True
True  <=> False = False
{-@ type TRUE  = {v:Bool | Prop v}       @-}
{-@ type FALSE = {v:Bool | not (Prop v)} @-}
{-@ deMorgan :: Bool -> Bool -> TRUE @-}
deMorgan :: Bool -> Bool -> Bool
deMorgan a b = not (a || b) <=> (not a && not b)
When running liquid Test.hs, I get the following output:
LiquidHaskell Copyright 2009-15 Regents of the University of California. All Rights Reserved.
**** DONE:  Parsed All Specifications ******************************************
**** DONE:  Loaded Targets *****************************************************
**** DONE:  Extracted Core using GHC *******************************************
Working   0%     [.................................................................]
Done solving.
**** DONE:  solve **************************************************************
**** DONE:  annotate ***********************************************************
**** RESULT: UNSAFE ************************************************************
 Test.hs:23:16-48: Error: Liquid Type Mismatch
 23 | deMorgan a b = not (a || b) <=> (not a && not b)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   Inferred type
     VV : Bool
   not a subtype of Required type
     VV : {VV : Bool | Prop VV}
   In Context
Now I'm by no means a LiquidHaskell expert, but I'm pretty sure something must be wrong. I have convinced myself that the identity holds a few years ago, but to make sure I called the function with every possible input, and eventually ran
λ: :l Test.hs 
λ: import Test.QuickCheck
λ: quickCheck deMorgan 
>>> +++ OK, passed 100 tests.
So I don't seem to have a typo in the Haskell code, the error must lie in the LiquidHaskell specification. It seems that LiquidHaskell cannot infer that the resulting Bool is strictly TRUE:
Inferred type
  VV : Bool
not a subtype of Required type
  VV : {VV : Bool | Prop VV}
What is my mistake here? Any help is appreciated!
PS: I'm using the z3 solver, and running GHC 7.10.3. LiquidHaskell version is 2009-15.
