以下是类型签名chunksOf
和splitPlaces
来自Data.List.Split
:
chunksOf :: Int -> [e] -> [[e]]
splitPlaces :: Integral a => [a] -> [e] -> [[e]]
Run Code Online (Sandbox Code Playgroud)
为什么某些功能(如chunksOf
)使用Int
而其他功能(如)使用splitPlaces
更通用的功能Integral a
?
在这个答案中,我试着看看界面不一致的历史原因.简介:似乎布伦特在运行中使一些函数更通用,以帮助制定QuickCheck属性.
splitPlaces
通用的?看起来Brent概括了类型,splitPlaces
以便更容易为该函数引入QuickCheck属性.QuickCheck属性使用newtype包装器来控制测试用例生成,并且通过Integral a
约束,splitPlaces
可以查看此newtype包装器以进行算术运算.也可以看看:
该补丁
概括了类型splitPlaces
并引入了QuickCheck属性.
有关这些newtype包装器的QuickCheck文档.
但是,这里有一个属性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
Run Code Online (Sandbox Code Playgroud)
请注意,QuickCheck会自动生成在传递之前ps
转换的列表.该函数删除了包装器,因此不必处理包装器本身.但是,它接收的是类型的参数而不是,因此它仍然需要在数字类型中是通用的.map unNN ps
splitPlaces
unNN
NonNegative
splitPlaces
NonNegative
[Integer]
[Int]
[NonNegative Integer]
代替[NonNegative Int]
?我怀疑该属性是错误的,[Int]
因为计算总和时算术溢出.QuickCheck甚至可以证明该属性是可证伪的,因为Arbitrary [NonNegative Integer]
实例最终将委托给arbitrarySizedBoundedIntegral
哪个可以生成非常大的值.
我想使用[NonNegative Integer]
相反可以通过 两种方式解决这个问题:
Integer
,不会发生溢出.Arbitrary Integer
实例委托arbitrarySizedIntegral
只生成小值的实例.所以我想允许任意积分类型的原因是QuickCheck属性会失败Int
但成功Integer
.
chunksOf
不通用?chunksOf
使用模式匹配的属性来删除newtype包装器.也可以看看:
这是以下属性之一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)
Run Code Online (Sandbox Code Playgroud)
请注意,此属性与QuickCheck自动生成的参数匹配,并将它们传递给chunksOf
没有newtype包装器的参数.对于测试所需的参数chunksOf
,这很容易做到,因为这些数字不是嵌套在其他类型中.与prop_splitPlaces_preserve
上面相比,转换[NonNegative Integer]
为[Integer]
或[Int]
需要比模式匹配更复杂的东西.
这里Arbitrary Int
和之间的区别Arbitrary Integer
并不重要,因为该属性不涉及任何可以触发算术溢出的操作.
归档时间: |
|
查看次数: |
222 次 |
最近记录: |