LiquidHaskell:尝试使用assume关键字,但数据类型不是数字

时间:2017-07-25 12:50:22

标签: haskell liquid-haskell

我试图为Data.Ratio模块编写一些规范。到目前为止,我有:

module spec Data.Ratio where

import GHC.Real

Data.Ratio.denominator :: GHC.Real.Integral a => r : GHC.Real.Ratio a -> {x:a | x > 0}

我验证的代码是:

{-@ die :: {v:String | false} -> a @-}
die msg = error msg

main :: IO ()
main = do
  let x = 3 % 5
  print $ denominator x
  if denominator x < 0
    then die "bad ending"
    else putStrLn "good ending"

判断代码是安全的,因为分母永远不会返回负值。

我发现这很奇怪,因为我可能刚刚写了x <= 0作为后置条件,根据Data.Ratio模块的文档是不可能的。显然,Liquid Haskell并没有将我的后置条件与denominator的实现进行比较。

我的理解是,由于未检查函数实现,我最好使用assume关键字:

assume Data.Ratio.denominator :: GHC.Real.Integral a => r : GHC.Real.Ratio a -> {x:a | x > 0}

然而,我得到:

Error: Bad Type Specification
 assumed type GHC.Real.denominator :: (Ratio a) -> {VV : a | VV > 0}
     Sort Error in Refinement: {VV : a_a2kc | VV > 0}
     Unbound Symbol a_a2kc
 Perhaps you meant: papp5, papp3, papp4, head, papp2, papp7, papp6, papp1, tail
  because
The sort a_a2kc is not numeric

我的问题是

  1. 如果LH强迫我在这种情况下使用assume关键字,如果它通过与功能实现进行比较显然没有验证我的精炼类型的正确性吗?
  2. 我认为我应该使用assume关键字吗?
  3. 为什么a突然不是数字?当我没有使用assume
  4. 时,它不是数字

1 个答案:

答案 0 :(得分:0)

不幸的是,'Numeric'字面意思是'Num',甚至不是它的子类。我们需要扩展LH以支持上面描述的形式的子类;我会为它创建一个问题,谢谢你指出!

现在,如果您将您的类型专门化,例如IntInteger然后LH正确抛出错误:

import GHC.Real

{-@ assume denom :: r:GHC.Real.Ratio Int -> {x:Int | x >= 0} @-}
denom :: GHC.Real.Ratio Int -> Int 
denom = denominator

{-@ die :: {v:String | false} -> a @-}
die msg = error msg

main :: IO ()
main = do
  let x = 3 % 5
  print $ denom x
  if denom x <= 0
    then die "bad ending"
    else putStrLn "good ending"

http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1504739852_3583.hs

如果您输出类型x > 0,那么它再次安全。

http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1504739907_3585.hs

再次感谢您指出Ratio问题!