【发布时间】:2019-02-04 18:32:13
【问题描述】:
问题
我对使用 LiquidHaskell 感到非常兴奋,但是,我不知道我需要在多大程度上修改我的原始 Haskell 代码才能满足 LiquidHaskell 的要求。
这是一个简单的例子,说明 Liquid 的规范如何适用于 String 类型,但不适用于 Text 类型。
对于 String 类型来说效果很好
示例
我定义了一个 Liquid 类型,我们说一个元组的值不能相同:
{-@ type NoRouteToHimself = {v:(_, _) | (fst v) /= (snd v)} @-}
然后,对于 String 类型规范,它工作得很好,如下所示:
{-@ strOk :: NoRouteToHimself @-}
strOk :: (String, String)
strOk = ("AA", "AB")
LiquidHaskel 输出 >> 结果:安全
{-@ strBad :: NoRouteToHimself @-}
strBad :: (String, String)
strBad = ("AA", "AA")
LiquidHaskel 输出 >> 结果:不安全
到目前为止一切顺利,让我们为 Text 类型定义相同的函数。
Text 类型出错了
示例
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text as Tx
{-@ foo :: NoRouteToHimself @-}
foo :: (Tx.Text, Tx.Text)
foo = ("AA", "AB")
预期结果:结果:安全
LiquidHaskell 输出:结果:不安全
..Example.hs:102:3-5: Error: Liquid Type Mismatch
102 | foo = ("AA", "AB")
^^^
Inferred type
VV : {v : (Data.Text.Internal.Text, Data.Text.Internal.Text) | x_Tuple22 v == ?a
&& x_Tuple21 v == ?b
&& snd v == ?a
&& fst v == ?b}
not a subtype of Required type
VV : {VV : (Data.Text.Internal.Text, Data.Text.Internal.Text) | fst VV /= snd VV}
In Context
?b : Data.Text.Internal.Text
?a : Data.Text.Internal.Text
显然 LiquidHaskell 在这种情况下无法评估元组的值。有什么建议吗?
【问题讨论】:
-
我认为您需要一个规范文件来定义一些必需的 Data.Text 公理。我怀疑liquidhaskell 对Data.Text 有任何了解,例如
fromString甚至可能不是单射的。不幸的是,我仍在挖掘规范文件到底是什么以及如何使用它(我今天刚开始玩 LH,所以不要绝望) -
part 4 of the tutorial 中提到了一些关于规格和假设的内容。
-
@luqui,确实,必须声明文件级规范“include/Data/String.spec”,我联系了 Ranjit Jhala 并建议在函数“Data.String”中创建具有此改进的 PR .fromString”。目前,LH 语句“{-@假设 Data.String.fromString :: x:_ -> {v:_ | v ~~ x} @-}”就足够了。我更喜欢这个选项,因为它不需要更改本机 haskell 代码。