我正在遵循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
答案 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
上实例化参数lo
和hi
分别使用0
和n
,顺便说一下 引擎推论出非负性。