为什么LiquidHaskell不能谨慎考虑?

时间:2019-06-17 07:38:49

标签: liquid-haskell

我正在遵循Liquid Haskell教程:

http://ucsd-progsys.github.io/liquidhaskell-tutorial/04-poly.html

,此示例失败:

module Test2 where

import Data.Vector
import Prelude hiding (length)

vectorSum :: Vector Int -> Int
vectorSum vec = go 0 0
  where
    go acc i
      | i < length vec  = go (acc + (vec ! i)) (i + 1)
      | otherwise       = acc

,出现以下错误:

Error: Liquid Type Mismatch

 10 |       | i < length vec  = go (acc + (vec ! i)) (i + 1)
                                   ^^^^^^^^^^^^^^^^^

   Inferred type
     VV : {v : GHC.Types.Int | v == acc + ?b}

   not a subtype of Required type
     VV : {VV : GHC.Types.Int | VV < acc
                                && VV >= 0}

   In Context
     ?b : GHC.Types.Int
     acc : GHC.Types.Int

问题是为什么?警卫(i

1 个答案:

答案 0 :(得分:0)

首先,我不知道您使用的是哪个版本的LH,但我遇到了完全相同的问题。该教程指出

LiquidHaskell验证vectorSum –确切地说,是对 向量访问vec!一世。验证成功是因为 LiquidHaskell能够自动推断

go :: Int -> {v:Int | 0 <= v && v <= sz} -> Int

表示第二个参数i在0和长度之间 的vec(含)。 LiquidHaskell使用此和i

他们还指出,该教程与当前版本的LiquidHaskell不兼容。

自编写本教程以来,LH的(finement-)type推断似乎已经发生了一些变化,可能比以前泛化了更多类型,从而导致了此问题。

问题不在于LH没有正确地找到后卫。问题在于它无法验证属性0 <= v

以下检查适用于LH 0.8.6.2版本:

{-@ LIQUID "--short-names"         @-}
{-@ LIQUID "--no-termination"      @-}
{-@ LIQUID "--reflection"          @-}

import Prelude hiding (length)
import Data.Vector 

{-@ go' :: v:Vector Int -> Int -> {i:Int | i>=0 } ->Int @-}
go' :: Vector Int -> Int -> Int -> Int
go' vec acc i
    | i < sz    = go' vec (acc + (vec ! i)) (i + 1)
    | otherwise = acc
    where sz = length vec

vecSum :: Vector Int -> Int
vecSum vec = go' vec 0 0

LH似乎本身就推断出go是一个函数,可以用小于0的整数调用(显然不是)。

我仍在使用该示例来说服LH这个事实。如果有人在此方面获得更多成功,请发表评论。


编辑:

我在同一教程中找到了以下段落;看来情况可能已经改变:

在呼叫loop 0 n 0 body上实例化参数lohi 分别使用0n,顺便说一下 引擎推论出非负性。