我的 quickCheck 类型声明有什么问题?
What's wrong with my quickCheck type declaration?
我推出自己的 elem
函数 elem'
elem' :: (Eq a) => a -> [a] -> Bool
elem' n ys = foldl (\acc p -> if (p == n) then True else False) False ys
似乎可行,但我想在 GHCi 中快速检查它,所以我 import Test.QuickCheck
verboseCheck (\a -> (\xs ->( (elem' a xs) == (elem a xs)) ) )
在测试函数上没有类型声明它测试正常,但那是因为它只测试空输入。
我的测试函数类型声明有问题:
verboseCheck (\a->(\xs->((elem' a xs)==(elem a xs))) :: Int->[Int]->Bool)
verboseCheck (\a->(\xs->((elem' a xs)==(elem a xs))) :: Char->[Char]->Bool)
第一个错误:
• Couldn't match expected type ‘[Int] -> Bool’
with actual type ‘Bool’
• Possible cause: ‘(==)’ is applied to too many arguments
In the expression: ((elem' a xs) == (elem a xs))
In the expression:
(\ xs -> ((elem' a xs) == (elem a xs))) :: Int -> [Int] -> Bool
In the first argument of ‘verboseCheck’, namely
‘(\ a
-> (\ xs -> ((elem' a xs) == (elem a xs))) ::
Int -> [Int] -> Bool)’
<interactive>:258:39: error:
• Couldn't match expected type ‘[()]’ with actual type ‘Int’
• In the second argument of ‘elem'’, namely ‘xs’
In the first argument of ‘(==)’, namely ‘(elem' a xs)’
In the expression: ((elem' a xs) == (elem a xs))
<interactive>:258:54: error:
• Couldn't match expected type ‘[()]’ with actual type ‘Int’
• In the second argument of ‘elem’, namely ‘xs’
In the second argument of ‘(==)’, namely ‘(elem a xs)’
In the expression: ((elem' a xs) == (elem a xs))
发生这种情况是因为 Haskell 认为您正在约束 lambda 表达式 \a->(\xs->((elem' a xs)==(elem a xs)))
的 return 类型 。如果您更习惯地格式化表达式,这可能更容易看到:
\a -> (\xs -> ((elem' a xs) == (elem a xs)))
对于 interpreter/compiler,这看起来像是一个 lambda 表达式,return 是另一个表达式。一切顺利。
但是,当您尝试使用类型对其进行注释时:
\a -> (\xs -> ((elem' a xs) == (elem a xs))) :: Int -> [Int] -> Bool
Haskell 认为您正在注释 return 类型 ,即最右侧与类型注释最接近的部分:(\xs -> ((elem' a xs) == (elem a xs)))
.
在 应用类型之前用方括号括起整个 lambda 表达式:
(\a -> (\xs -> ((elem' a xs) == (elem a xs)))) :: Int -> [Int] -> Bool
您现在可以 verboseCheck
该表达式:
Prelude Test.QuickCheck> verboseCheck ((\a -> (\xs -> ((elem' a xs) == (elem a xs)))) :: Int -> [Int] -> Bool)
Passed:
0
[]
Passed:
0
[]
Passed:
0
[-2,0]
Failed:
1
[2,1,-1]
Passed:
0
[2,1,-1]
Passed:
1
[]
Failed:
1
[1,-1]
Passed:
0
[1,-1]
Passed:
1
[]
Passed:
1
[-1]
Passed:
1
[1]
Passed:
1
[0,-1]
Passed:
1
[1,1]
Failed:
1
[1,0]
Passed:
0
[1,0]
Passed:
1
[]
Passed:
1
[0]
Passed:
1
[1]
Passed:
1
[0,0]
*** Failed! Falsified (after 4 tests and 2 shrinks):
1
[1,0]
然而,大多数括号都是多余的,这可能是造成混淆的原因。您可以将表达式简化为:
verboseCheck ((\a xs -> elem' a xs == elem a xs) :: Int -> [Int] -> Bool)
verboseCheck ((\a xs -> elem' a xs == elem a xs) :: Char -> [Char] -> Bool)
我推出自己的 elem
函数 elem'
elem' :: (Eq a) => a -> [a] -> Bool
elem' n ys = foldl (\acc p -> if (p == n) then True else False) False ys
似乎可行,但我想在 GHCi 中快速检查它,所以我 import Test.QuickCheck
verboseCheck (\a -> (\xs ->( (elem' a xs) == (elem a xs)) ) )
在测试函数上没有类型声明它测试正常,但那是因为它只测试空输入。
我的测试函数类型声明有问题:
verboseCheck (\a->(\xs->((elem' a xs)==(elem a xs))) :: Int->[Int]->Bool)
verboseCheck (\a->(\xs->((elem' a xs)==(elem a xs))) :: Char->[Char]->Bool)
第一个错误:
• Couldn't match expected type ‘[Int] -> Bool’
with actual type ‘Bool’
• Possible cause: ‘(==)’ is applied to too many arguments
In the expression: ((elem' a xs) == (elem a xs))
In the expression:
(\ xs -> ((elem' a xs) == (elem a xs))) :: Int -> [Int] -> Bool
In the first argument of ‘verboseCheck’, namely
‘(\ a
-> (\ xs -> ((elem' a xs) == (elem a xs))) ::
Int -> [Int] -> Bool)’
<interactive>:258:39: error:
• Couldn't match expected type ‘[()]’ with actual type ‘Int’
• In the second argument of ‘elem'’, namely ‘xs’
In the first argument of ‘(==)’, namely ‘(elem' a xs)’
In the expression: ((elem' a xs) == (elem a xs))
<interactive>:258:54: error:
• Couldn't match expected type ‘[()]’ with actual type ‘Int’
• In the second argument of ‘elem’, namely ‘xs’
In the second argument of ‘(==)’, namely ‘(elem a xs)’
In the expression: ((elem' a xs) == (elem a xs))
发生这种情况是因为 Haskell 认为您正在约束 lambda 表达式 \a->(\xs->((elem' a xs)==(elem a xs)))
的 return 类型 。如果您更习惯地格式化表达式,这可能更容易看到:
\a -> (\xs -> ((elem' a xs) == (elem a xs)))
对于 interpreter/compiler,这看起来像是一个 lambda 表达式,return 是另一个表达式。一切顺利。
但是,当您尝试使用类型对其进行注释时:
\a -> (\xs -> ((elem' a xs) == (elem a xs))) :: Int -> [Int] -> Bool
Haskell 认为您正在注释 return 类型 ,即最右侧与类型注释最接近的部分:(\xs -> ((elem' a xs) == (elem a xs)))
.
在 应用类型之前用方括号括起整个 lambda 表达式:
(\a -> (\xs -> ((elem' a xs) == (elem a xs)))) :: Int -> [Int] -> Bool
您现在可以 verboseCheck
该表达式:
Prelude Test.QuickCheck> verboseCheck ((\a -> (\xs -> ((elem' a xs) == (elem a xs)))) :: Int -> [Int] -> Bool)
Passed:
0
[]
Passed:
0
[]
Passed:
0
[-2,0]
Failed:
1
[2,1,-1]
Passed:
0
[2,1,-1]
Passed:
1
[]
Failed:
1
[1,-1]
Passed:
0
[1,-1]
Passed:
1
[]
Passed:
1
[-1]
Passed:
1
[1]
Passed:
1
[0,-1]
Passed:
1
[1,1]
Failed:
1
[1,0]
Passed:
0
[1,0]
Passed:
1
[]
Passed:
1
[0]
Passed:
1
[1]
Passed:
1
[0,0]
*** Failed! Falsified (after 4 tests and 2 shrinks):
1
[1,0]
然而,大多数括号都是多余的,这可能是造成混淆的原因。您可以将表达式简化为:
verboseCheck ((\a xs -> elem' a xs == elem a xs) :: Int -> [Int] -> Bool)
verboseCheck ((\a xs -> elem' a xs == elem a xs) :: Char -> [Char] -> Bool)