gpt4 book ai didi

haskell - 为什么某些 Data.List.Split 函数使用 `Int` 而其他函数使用 `Integral a` ?

转载 作者:行者123 更新时间:2023-12-03 14:11:39 24 4
gpt4 key购买 nike

这是 chunksOf 的类型签名和 splitPlaces 来自 Data.List.Split :

chunksOf :: Int -> [e] -> [[e]]
splitPlaces :: Integral a => [a] -> [e] -> [[e]]

为什么某些函数(如 chunksOf )使用 Int而其他人(如 splitPlaces )使用更通用的 Integral a ?

最佳答案

在这个答案中,我尝试查看界面不一致的历史原因。总结:Brent 似乎在运行中使一些函数更加通用,以帮助制定 QuickCheck 属性。

为什么是 splitPlaces通用的?

Brent 似乎概括了 splitPlaces 的类型。以便更轻松地为该函数引入 QuickCheck 属性。 QuickCheck 属性使用新类型包装器来控制测试用例的生成,并使用 Integral a约束,splitPlaces可以通过这个新类型包装器来查看算术运算。也可以看看:

  • The patch
    概括 splitPlaces 的类型并介绍了 QuickCheck 属性。
  • The QuickCheck documentation关于这些新型包装器。

  • 然而,这里是关于 splitPlaces 的属性之一。 :
    prop_splitPlaces_preserve :: [NonNegative Integer] -> [Elt] -> Bool
    prop_splitPlaces_preserve ps l = concat (splitPlaces ps' l) == genericTake (sum ps') l
    where ps' = map unNN ps

    请注意,QuickCheck 会自动生成列表 psmap unNN ps 转换在传递给 splitPlaces 之前. unNN函数删除 NonNegative包装,所以 splitPlaces不必处理 NonNegative包装器本身。但是,它接收类型为 [Integer] 的参数。而不是 [Int] ,所以它仍然需要在数字类型中是通用的。

    使用 [NonNegative Integer] 有什么意义?而不是 [NonNegative Int] ?

    我怀疑 [Int] 的属性是错误的因为在计算总和时算术溢出。该属性甚至可能被 QuickCheck 证伪,因为 Arbitrary [NonNegative Integer]实例最终将委托(delegate)给 arbitrarySizedBoundedIntegral 这可以产生非常大的值。

    我猜想使用 [NonNegative Integer]而是通过两种方式规避这个问题:
  • Integer ,不会发生溢出。
  • Arbitrary Integer实例委托(delegate)给 arbitrarySizedIntegral 这只产生小的值。

  • 所以我猜想允许任意 Integral 类型的原因是 QuickCheck 属性对于 Int 会失败。但成功 Integer .

    为什么是 chunksOf不是通用的?
    chunksOf 的属性使用模式匹配删除新类型包装器。也可以看看:
  • The patch介绍 splitEvery 的属性.
  • The patch重命名 splitEverychunksOf .

  • 这是关于 chunksOf 的属性之一:
    prop_chunksOf_all_n :: Positive Int -> NonEmptyList Elt -> Bool
    prop_chunksOf_all_n (Positive n) (NonEmpty l) = all ((==n) . length) (init $ chunksOf n l)

    请注意,此属性匹配由 QuickCheck 自动生成的参数并将它们传递给 chunksOf。没有 newtype 包装器。对于测试所需的参数 chunksOf ,这很容易做到,因为数字没有嵌套在其他类型中。与 prop_splitPlaces_preserve 进行比较上面,其中转换 [NonNegative Integer][Integer][Int]需要比模式匹配更复杂的东西。
    Arbitrary Int 之间的区别和 Arbitrary Integer在这里没关系,因为该属性不涉及任何可以触发算术溢出的操作。

    关于haskell - 为什么某些 Data.List.Split 函数使用 `Int` 而其他函数使用 `Integral a` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18427445/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com