Haskell - 检查列表中的所有项是否大于1

时间:2015-03-05 23:36:09

标签: list function haskell

如果所有项都大于1,我需要返回一个布尔值True,否则返回False。这是我的尝试......

greaterOne :: Ord a=>a->Bool
greaterOne x = x > 1

checkLis :: Ord a=>[a]->Bool
checkLis [] = True
checkLis (x:xs)
    | greaterOne x = checkLis xs
    | otherwise = False

这是我得到的错误,我一直在努力修复它,但无济于事......

Could not deduce (Num a) arising from the literal ‘1’
from the context (Ord a)
  bound by the type signature for greaterOne :: Ord a => a -> Bool
  at pract.hs:23:15-28
Possible fix:
  add (Num a) to the context of
    the type signature for greaterOne :: Ord a => a -> Bool
In the second argument of ‘(>)’, namely ‘1’
In the expression: x > 1
In an equation for ‘greaterOne’: greaterOne x = x > 1

1 个答案:

答案 0 :(得分:5)

暂时考虑一下这个表达式,

x > 1

我们确信1是一个数字,我们需要将其与x进行比较并返回结果。但我们不知道x的类型。如果x实际上是一个字符串怎么办?然后表达式将失败。但是Haskell的类型系统很强大,它会感觉到这里的混乱,并要求你手动修复它。它甚至为你提供了一个提示,

Possible fix:
  add (Num a) to the context of
    the type signature for greaterOne :: Ord a => a -> Bool

因此,您需要做的就是明确指定a是类Num的实例,如GHC建议的那样

checkLis :: Ord a => Num a => [a] -> Bool
checkLis [] = True
......
greaterOne :: Ord a => Num a => a -> Bool
greaterOne x = x > 1

现在,我们说,a不仅仅是有序数据类型,而且实际上是类Num


您实际上可以使用内置函数all来执行此操作。

> all greaterOne [2, 2, 3]
True
> all greaterOne [1, 2, 3]
False

all函数检查函数是否作为第一个参数传递,对列表中的每个元素求值为True


我们实际上可以只用部分表达式来做同样的事情,比如这个

Prelude> all (> 1) [2, 2, 3]
True
Prelude> all (> 1) [1, 2, 3]
False