Liquid Haskell使用PS创建新的字节串

时间:2018-11-30 17:58:13

标签: haskell liquid-haskell

我正在从Haskell对C进行一些绑定,并尝试使用LiquidHaskell使它更安全。在LH类型注释中指定字节串的长度时遇到了麻烦。

我在LiquidHaskell中具有增强的ByteString类型,其中包括其长度:

{-@ type ByteString Blen = {v:B.ByteString | bslen v == Blen} @-}

运行Liquidhaskell时出现以下错误:

**** RESULT: UNSAFE ************************************************************


 /home/t/liquidproblem/Main.hs:47:3-22: Error: Liquid Type Mismatch

 47 |   Bi.PS foreignPtr 0 l
        ^^^^^^^^^^^^^^^^^^^^

   Inferred type
     VV : {v : Data.ByteString.Internal.ByteString | 0 <= bslen v
                                                     && bslen v == stringlen v}

   not a subtype of Required type
     VV : {VV : Data.ByteString.Internal.ByteString | bslen VV == l}

   In Context
     l : {l : GHC.Types.Int | l >= 0}

第47行是:

44 {-@ makeBs :: ForeignPtr Word8 -> l:NonNeg -> ByteString l @-}
45 makeBs :: F.ForeignPtr F.Word8 -> Int -> B.ByteString
46 makeBs foreignPtr l =
47   Bi.PS foreignPtr 0 l

(我知道这似乎是一个愚蠢的功能,但之所以加入了该功能,是因为调试过程是要分解出位并在它们上放LH注释,直到发现问题为止。)

相关进口是:

import qualified Data.ByteString.Internal as Bi
import qualified Data.ByteString as B
import qualified Foreign as F

LH NonNeg类型是

{-@ type NonNeg = {i:Int | i >= 0} @-}

1 个答案:

答案 0 :(得分:1)

LiquidHaskell不知道ByteString返回的makeBs的长度为l,并且无法从可用信息中证明这一点。

您会知道,因为您知道PS构造函数的第三个参数是长度。因此,此时您有两个(或可能一个)选项:

  1. 您可以尝试告诉LH您对PS构造函数的了解,并给它一个注释,例如 {-@ Bi.PS :: _ -> _ -> l:NonNeg -> ByteString l @-}。我尝试了一下,但效果不佳,因为PS签名中存在内部GHC类型,LH似乎不太擅长处理。 YMMV。或者,您可以:
  2. 忘记注释PS并用assume标记自己的功能:{-@ assume makeBs :: ForeignPtr Word8 -> l:NonNeg -> ByteString l @-}。当然,如果标记为assume的函数变大,这会冒更大的风险-虽然看起来很傻,但是如果您选择这种方法,则可能希望保持makeBs左右。