【问题标题】:Hspec & QuickCheck - Ambiguous type variable a0?Hspec & QuickCheck - 不明确的类型变量 a0?
【发布时间】:2018-10-14 13:26:44
【问题描述】:

我在 Haskell 中编写了一个函数,它接受一个任意元素的列表并返回(映射)一个元组列表。每个元组包含原始元素和一个分数,列表中的所有分数都加 1(因此我只需使用 1 ``div`` length xs 计算一次分数并将其应用于所有元素)。这是代码:

uniform :: [a] -> [(a, Int)]
uniform xs = map (\x -> (x, prob)) xs
  where prob = 1 `div` (length xs)

(免责声明:这实际上是一个稍微简化的版本,但我正在产生完全相同的行为,所以希望这就足够了)。

我正在尝试通过使用 Hspec 和 Quickcheck 的基于属性的测试来解决这个问题:

spec = do
    describe "uniform" $ do

        it "produces a uniform distribution summing to 1" $ property $
            let totalProbability ((_, p):xs) = p + (totalProbability xs)
            in (\xs -> (totalProbability $ uniform xs) `shouldBe` 1)

但是当我运行它时,我得到了这个错误:

• Ambiguous type variable ‘a0’ arising from a use of ‘property’
  prevents the constraint ‘(Arbitrary a0)’ from being solved.
  Probable fix: use a type annotation to specify what ‘a0’ should be.
  These potential instances exist:
    instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b)
      -- Defined in ‘Test.QuickCheck.Arbitrary’
    instance Arbitrary Ordering
      -- Defined in ‘Test.QuickCheck.Arbitrary’
    instance Arbitrary Integer
      -- Defined in ‘Test.QuickCheck.Arbitrary’
    ...plus 19 others
    ...plus 62 instances involving out-of-scope types
    (use -fprint-potential-instances to see them all)
• In the second argument of ‘($)’, namely
    ‘property
       $ let totalProbability ((_, p) : xs) = p + (totalProbability xs)
         in (\ xs -> (totalProbability $ uniform xs) `shouldBe` 1)’
  In a stmt of a 'do' block:
    it "produces a uniform distribution summing to 1"
      $ property
          $ let totalProbability ((_, p) : xs) = p + (totalProbability xs)
            in (\ xs -> (totalProbability $ uniform xs) `shouldBe` 1)
  In the second argument of ‘($)’, namely
    ‘do it "produces a uniform distribution summing to 1"
          $ property
              $ let totalProbability ((_, p) : xs) = ...
                in (\ xs -> (totalProbability $ uniform xs) `shouldBe` 1)’

| 12 |它“产生一个总和为 1 的均匀分布”$ 属性 $ | ^^^^^^^^^^...

我猜在某个地方我没有向 QuickCheck 提供有关如何生成测试值的足够信息,但我不确定从这里去哪里。

任何帮助将不胜感激。

谢谢!

【问题讨论】:

  • xs 未在let ... 部分的let-in 语句中定义。

标签: haskell quickcheck hspec


【解决方案1】:

您需要为xs 指定一个类型:这是一个字符串列表吗?整数?布尔值?这样 QuickCheck 可以生成该类型的随机样本。

你可以写,例如:

...
in (\xs -> (totalProbability $ uniform (xs :: [Int])) `shouldBe` 1)

【讨论】:

  • 对,好吧,我认为它可能是完全一样的。问题是我希望这个函数适用于任何类型的 xs。由于地图只是将其包装起来,因此它的类型实际上并不重要。这不是快速检查处理的事情吗?在这种情况下我需要为不同类型提供多个属性,还是可以编写某种自定义生成器?
  • @Raiden616 QuickCheck 不知道类型没关系。在这种情况下,您可以看到uniform 只添加了统一的权重,而totalProbability 将这些权重相加而忽略了它们配对的数据。所以,确实类型并不重要。 (即使不查看uniform 代码,也可以使用参数化和一些理论计算机科学来证明这一点)。在这种情况下,您只能测试[Int],因为如果您的代码适用于该类型,那么它也适用于任何其他类型。可以这么说,不需要使用 QuickCheck 来“生成随机类型”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多