如何修复对函数的有效 属性 完成的 quickCheck 的匹配错误?
How to fix a matching error on a quickCheck done on a valid property of a function?
我想编写一个函数 search :: String -> Char -> [Int]
来 returns 第一个参数中所有出现的第二个参数的位置。例如:
search "Bookshop" 'o' == [1,2,6]
search "senselessness" 's' == [0,3,7,8,11,12]
根据@Will Ness,最终代码如下:
search :: (Num b, Eq a, Enum b) => [a] -> a -> [b]
search s char = [ i | (i,c) <- zip [0..] s, c==char]
我想用 属性 搜索做一个 QuickCheck 测试,即输出的元素不能多于第一个参数。如何做到这一点?我的骨架代码如下:
prop_search :: String -> Int -> Int -> Bool
prop_search x char = if length search x char <= length x then True else False
这会产生匹配错误,其中:
* Couldn't match expected type `Int -> Bool'
with actual type `Bool'
* In the expression: False
为什么会这样?
prop_search
有几个问题。虽然 Haskell 中的编译器消息可能有点令人生畏,但第一个故障排除技巧是要意识到(除非您使用该语言的某些高级扩展)类型注释是多余的。编译器不需要类型注释,但最好包含它们,因为它有助于提高可读性。
因此,首先尝试查看表达式本身是否编译。在这里,我只使用 GHCi:
Prelude> prop_search x char = if length search x char <= length x then True else False
<interactive>:18:25: error:
* Couldn't match expected type `t a -> t1 -> Int'
with actual type `Int'
* The function `length' is applied to three arguments,
but its type `([()] -> () -> [Integer]) -> Int' has only one
In the first argument of `(<=)', namely `length search x char'
In the expression: length search x char <= length x
* Relevant bindings include
char :: t1 (bound at <interactive>:18:15)
x :: t a (bound at <interactive>:18:13)
prop_search :: t a -> t1 -> Bool (bound at <interactive>:18:1)
所以那是行不通的,但这是与 OP 中发布的错误不同的另一个错误。它说什么?
The function `length' is applied to three arguments
length
的类型是什么?
Prelude> :t length
length :: Foldable t => t a -> Int
length
是一个接受单个 Foldable
参数和 returns 一个 Int
的函数。它需要一个而不是三个参数。
然而,在表达式 length search x char
中,Haskell 编译器看起来好像 length
是用三个参数调用的。
您想要测量 search x char
的 length
,因此将其分组:
prop_search x char = if length (search x char) <= length x then True else False
现在可以编译了,这意味着你可以查询它的类型:
Prelude> :t prop_search
prop_search :: Eq a => [a] -> a -> Bool
请注意,这不是 OP 中给出的类型。该函数接受 两个 个参数 - 而不是三个。
如果需要,您可以复制该推断类型并将其作为类型注释添加到函数中。
最后,当你发现自己在写 if x then True else False
时,你可以只写 x
:
prop_search x char = length (search x char) <= length x
这仍然有相同的类型:
Prelude> :t prop_search
prop_search :: Eq a => [a] -> a -> Bool
总之,您可能希望这样编写函数:
prop_search :: Eq a => [a] -> a -> Bool
prop_search x char = length (search x char) <= length x
我想编写一个函数 search :: String -> Char -> [Int]
来 returns 第一个参数中所有出现的第二个参数的位置。例如:
search "Bookshop" 'o' == [1,2,6]
search "senselessness" 's' == [0,3,7,8,11,12]
根据@Will Ness,最终代码如下:
search :: (Num b, Eq a, Enum b) => [a] -> a -> [b]
search s char = [ i | (i,c) <- zip [0..] s, c==char]
我想用 属性 搜索做一个 QuickCheck 测试,即输出的元素不能多于第一个参数。如何做到这一点?我的骨架代码如下:
prop_search :: String -> Int -> Int -> Bool
prop_search x char = if length search x char <= length x then True else False
这会产生匹配错误,其中:
* Couldn't match expected type `Int -> Bool'
with actual type `Bool'
* In the expression: False
为什么会这样?
prop_search
有几个问题。虽然 Haskell 中的编译器消息可能有点令人生畏,但第一个故障排除技巧是要意识到(除非您使用该语言的某些高级扩展)类型注释是多余的。编译器不需要类型注释,但最好包含它们,因为它有助于提高可读性。
因此,首先尝试查看表达式本身是否编译。在这里,我只使用 GHCi:
Prelude> prop_search x char = if length search x char <= length x then True else False
<interactive>:18:25: error:
* Couldn't match expected type `t a -> t1 -> Int'
with actual type `Int'
* The function `length' is applied to three arguments,
but its type `([()] -> () -> [Integer]) -> Int' has only one
In the first argument of `(<=)', namely `length search x char'
In the expression: length search x char <= length x
* Relevant bindings include
char :: t1 (bound at <interactive>:18:15)
x :: t a (bound at <interactive>:18:13)
prop_search :: t a -> t1 -> Bool (bound at <interactive>:18:1)
所以那是行不通的,但这是与 OP 中发布的错误不同的另一个错误。它说什么?
The function `length' is applied to three arguments
length
的类型是什么?
Prelude> :t length
length :: Foldable t => t a -> Int
length
是一个接受单个 Foldable
参数和 returns 一个 Int
的函数。它需要一个而不是三个参数。
然而,在表达式 length search x char
中,Haskell 编译器看起来好像 length
是用三个参数调用的。
您想要测量 search x char
的 length
,因此将其分组:
prop_search x char = if length (search x char) <= length x then True else False
现在可以编译了,这意味着你可以查询它的类型:
Prelude> :t prop_search
prop_search :: Eq a => [a] -> a -> Bool
请注意,这不是 OP 中给出的类型。该函数接受 两个 个参数 - 而不是三个。
如果需要,您可以复制该推断类型并将其作为类型注释添加到函数中。
最后,当你发现自己在写 if x then True else False
时,你可以只写 x
:
prop_search x char = length (search x char) <= length x
这仍然有相同的类型:
Prelude> :t prop_search
prop_search :: Eq a => [a] -> a -> Bool
总之,您可能希望这样编写函数:
prop_search :: Eq a => [a] -> a -> Bool
prop_search x char = length (search x char) <= length x