简体   繁体   English

Haskell 检查列表是否为奇数

[英]Haskell check if list is odd

I need to check if a list only contains odd numbers, bigger than 10. This is what I did.我需要检查一个列表是否只包含大于 10 的奇数。这就是我所做的。

f :: [Int] -> Bool
f xs= [x |x<-xs, x >10,  odd x]

Why does it not work?为什么它不起作用? Thanks谢谢

When you write [x |x<-xs, x >10, odd x] you're making up a list of Int s, a [Int] , not a Bool ean.当你写[x |x<-xs, x >10, odd x]你正在组成一个Int的列表,一个[Int] ,而不是一个Bool For instance you can verify that [x | x <- [1..20], x > 10, odd x]例如,您可以验证[x | x <- [1..20], x > 10, odd x] [x | x <- [1..20], x > 10, odd x] is the list [11,13,15,17,19] . [x | x <- [1..20], x > 10, odd x]是列表[11,13,15,17,19] So it does contain the numbers that you want, but how do you tell that those are all of the numebrers in xs ?所以它确实包含你想要的数字,但是你怎么知道这些是xs中的所有数字?

You could certainly equate that list to xs itself, and that would work:您当然可以将该列表等同于xs本身,这将起作用:

f xs = xs == [x |x<-xs, x >10,  odd x]

This way the == ensures that when you only take odd numbers greater than 10 from xs you get back exactly xs , meaning that all numbers satisfy the predicate.这样==确保当你只从xs取大于 10 的奇数时,你会得到准确的xs ,这意味着所有数字都满足谓词。

Maybe this is the mistake you were looking for.也许这就是你要找的错误。

I'm not sure whether this solution traverses xs twice (once to extract the entries satisfying the predicate, and once to check for equality) or not.我不确定这个解决方案是否遍历xs两次(一次提取满足谓词的条目,一次检查相等性)。 It looks very simple, so I can't help but think that the list is traversed only once.看起来很简单,所以我不禁想到这个列表只遍历了一次。


Anyway, another strategy is to stick to your request: you want all numbers x from the list xs for which odd x and x > 10 are both True :无论如何,另一种策略是坚持您的要求:您希望列表xs all odd xx > 10都为True数字x

f :: [Int] -> Bool
f xs = all (\x -> odd x && x > 10) xs

By noticing that both sides have a trailing xs , you can reduce the definition:通过注意到双方都有一个尾随xs ,你可以减少定义:

f :: [Int] -> Bool
f = all (\x -> odd x && x > 10)

And that lambda, if you want, could be define more succintly as (odd & (> 10)) , thus getting如果你愿意,这个 lambda 可以更简洁地定义为(odd & (> 10)) ,从而得到

f :: [Int] -> Bool
f = all (odd & (> 10))

provided you import Control.Monad (liftM2) and define如果您import Control.Monad (liftM2)并定义

(&) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(&) = liftM2 (&&)

Your type signature mentions that the function returns a boolean value, but your proposed body returns a list of numbers.您的类型签名提到该函数返回一个布尔值,但您建议的主体返回一个数字列表。 Haskell has no automatic conversions such as Lisp. Haskell 没有像 Lisp 那样的自动转换。

Should you wish to stick to pedestrian code, you could get the sublist of offending numbers, and just check that the sublist is empty.如果你想坚持行人代码,你可以获得违规号码的子列表,只需检查子列表是否为空。

f :: [Int] -> Bool
f xs = let offenders = [x | x <- xs, x <= 10  ||  even x]
       in   (null offenders)

Should you want something a bit more haskell-ish, you can use the sequence :: (Traversable t, Monad m) => t (ma) -> m (ta) polymorphic library function to turn a list of predicates into a single function returning a list of boolean values, then pass that list to and .如果你想要一些更像 Haskell 的东西,你可以使用sequence :: (Traversable t, Monad m) => t (ma) -> m (ta)多态库函数将谓词列表转换为单个函数返回一个布尔值列表,然后将该列表传递给and That checks one number.那检查一个数字。

Then use all to apply these checks to all numbers in the input list.然后使用all将这些检查应用于输入列表中的所有数字。 Like this:像这样:

f2 :: [Int] -> Bool
f2 = all (and . sequence [(>10), odd])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM