I\'ve been trying to define a function which, given a list of Integers and an Integer n, returns a Boolean indicating whether n occurs exactly once in the list.
I have t
once :: (Eq a) => [a] -> a -> Bool
once xs x = (== 1) $ length $ filter (== x) xs
As I thought my former solution was ugly, I asked in another forum and got this as answer:
once :: Eq a => a -> [a] -> Bool
once x = (== [x]) . filter (== x)
I think you can't write that function much nicer, and in contrast to the accepted answer it's lazy.
Well, you can filter the list, then see how many elements are in the resulting filter, right?
To get you started:
> filter (== 2) [1,2,3,4,5]
[2]
> filter (== 2) [1,2,3,4,5,2,2]
[2,2,2]
And to fold your list down to a Bool value, here, an example where we test if a list has three elements, returning a Bool:
> isThree (a:b:c:[]) = True
> isThree _ = False
So it is just a short matter of composing such functions:
> isThree . filter (==2)
or your variant (e.g. matching for lists of length 1).
Here is another version:
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)
Of course it can't deal with infinite lists that contain zero or one x, but at least it terminates in case of more than one occurrence of x.