Haskell- return 如果键在关联列表中则为真

Haskell- return True if key is in associative list

我正在尝试创建一个接受字符串作为参数和 returns 布尔值的函数 True 如果字符串作为键值存在于以下关联列表中:

lis = [("Kingston", [12.2, 17.3, 9.1]), ("Ottawa", [10.0, 13.9, 8.2])]

这是我的功能,如果可能的话,我希望能够使用列表理解来做到这一点:

check :: String -> [(String,a)] -> Bool
check val alist
    | [ key | (key,num)<-alist, key==val] = True
    | otherwise = False

我得到的错误是:

Couldn't match expected type ‘Bool’ with actual type ‘[String]’

谁能告诉我我的错误是什么?

在haskell中,守卫应该评估为一个布尔值。所以,像这样的东西会起作用:

check :: String -> [(String,a)] -> Bool
check val alist
    | length [ key | (key,num) <-alist, key==val] >= 1 = True
    | otherwise = False

但请注意,这将必须遍历整个列表。

而下面的代码不需要遍历整个列表,效率更高:

check :: String -> [(String,a)] -> Bool
check val alist
    | efficientCheck [ key | (key,num) <-alist, key==val] = True
    | otherwise = False

efficientCheck :: [a] -> Bool
efficientCheck (x:xs) = True
efficientCheck _ = False

演示:

λ> check "bye" [("hi",3)]
False
λ> check "hi" [("hi",3),("bye",4)]
True

您正在守卫中使用类型为 [String] 的列表推导,其中需要 Bool

您需要做的是检查该列表理解是否为空。例如,使用 null.

check :: String -> [(String,a)] -> Bool
check val alist = not $ null [ key | (key,num) <- alist, key==val ]

保护子句中的表达式必须计算为 Bool。这不是 Python,它不会自动发生。尝试

check val alist
    | not $ null [key | (key, num) <- alist, key == val] = True
    | otherwise = False

但这可以简单地写成

check val alist = not $ null [key | (key, num) <- alist, key == val]

因为守卫只是检查值是 True 还是 False