我一直在尝试定义一个函数,给定一个整数列表和一个整数n,返回一个布尔值,指示n是否恰好在列表中出现一次。
我有这个,但它不起作用,我无法弄清楚
once :: [a] -> (a -> Bool) -> Bool
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
An example of what I want would be:
Main> once [2,3,2,4] 2
False
Main> once [1..100] 2
True
答案 0 :(得分:6)
我认为我以前的解决方案很难看,我在another forum询问并得到了答案:
once :: Eq a => a -> [a] -> Bool
once x = (== [x]) . filter (== x)
我认为你不能更好地编写这个功能,与接受的答案相比,它是懒惰的。
答案 1 :(得分:2)
那么,您可以过滤列表,然后查看生成的过滤器中有多少元素,对吧?
为了帮助您入门:
> filter (== 2) [1,2,3,4,5]
[2]
> filter (== 2) [1,2,3,4,5,2,2]
[2,2,2]
将列表折叠为Bool值,这里是一个示例,我们测试列表是否有三个元素,返回一个Bool:
> isThree (a:b:c:[]) = True
> isThree _ = False
因此,撰写此类函数只是一个短暂的问题:
> isThree . filter (==2)
或您的变体(例如,匹配长度为1的列表)。
答案 2 :(得分:2)
once :: (Eq a) => [a] -> a -> Bool
once xs x = (== 1) $ length $ filter (== x) xs
答案 3 :(得分:0)
这是另一个版本:
once x = not . (\xs -> null xs || x `elem` tail xs) . dropWhile (/= x)
--lambda hater version
import Control.Applicative
once x = not . ((||) <$> null <*> (elem x).tail) . dropWhile (/= x)
当然它不能处理包含零或一个x的无限列表,但至少它会在x出现多次的情况下终止。