5

我在用 LiquidHaskell 证明以下定律时遇到了麻烦:

德摩根定律

它被称为(之一)德摩根定律,并且简单地指出or两个值的否定必须与每个值and的否定相同。它已经被证明了很长时间,并且是 LiquidHaskell教程中的一个示例。我按照教程进行操作,但未能通过以下代码:

-- 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)

运行时liquid Test.hs,我得到以下输出:

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

现在我绝不是 LiquidHaskell 专家,但我很确定一定有问题。几年前我已经说服自己该身份成立,但为了确保我用所有可能的输入调用了该函数,并最终运行

λ: :l Test.hs 
λ: import Test.QuickCheck
λ: quickCheck deMorgan 
>>> +++ OK, passed 100 tests.

所以我在 Haskell 代码中似乎没有错字,错误一定在 LiquidHaskell 规范中。似乎 LiquidHaskell 无法推断出结果Bool是严格的TRUE

Inferred type
  VV : Bool

not a subtype of Required type
  VV : {VV : Bool | Prop VV}

我的错误是什么?任何帮助表示赞赏!

PS:我正在使用z3求解器,并运行 GHC 7.10.3。LiquidHaskell 版本是2009-15.

4

1 回答 1

8

LiquidHaskell 无法证明您的程序是安全的,因为它没有足够强大的类型用于(<=>). 我们确实推断函数的类型,但推断是基于程序中的其他类型签名。具体来说,我们需要弄清楚

{-@ (<=>) :: p:Bool -> q:Bool -> {v:Bool | Prop v <=> (Prop p <=> Prop q)} @-}

Prop语法是我们如何将 Haskell 提升Bool为 SMT 布尔值。)

为了让 LiquidHaskell 推断出这种类型,它需要Prop v <=> (Prop p <=> Prop q)在另一个类型签名中的某处看到一个谓词(对于 some vpq)。这个片段不会出现在任何地方,所以我们需要明确地提供签名。

这是 LiquidHaskell 的一个不幸的限制,但对于保持可判定性至关重要。

PS:这是您示例的工作版本的链接。 http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1461434240_7574.hs

于 2016-04-23T18:05:40.030 回答