我的 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)