Now, I'm still learning haskell (to configure my xmonad wm), so bear with me.
I've written this function:
doesNameBeginWith :: String -> Query Bool
doesNameBeginWith str = fmap ( str `isPrefixOf`) (stringProperty "WM_NAME")
Which will check the start of the WM_NAME X property against my str. I can compose it like this:
isMusic = doesNameBeginWith "MPD:" <||> doesNameBeginWith "ncmpcpp"
It works. Now I want to write a functions with this signature:
[String] -> Query Bool
so that I can call it like this:
isMusic = doesNameBeginWith ["MPD:", "ncmpcpp"]
The idea was to use foldr1 to parse the string list, but I can't figure out the sintax to get the head of the list... something like this:
doesNameBeginWith :: [String] -> Query Bool
doesNameBeginWith str = foldr1 (<||>) . fmap ( (head str) `isPrefixOf`) (stringProperty "WM_NAME")
EDIT 1: as leftaroundabout suggested, I can combine two functions to get what I want:
doesNameBeginWithL :: [String] -> Query Bool
doesNameBeginWithL = foldr1 (<||>) . map doesNameBeginWith
But I'm still hoping for a more direct way and to understand how list heads could be used in this situation!
EDIT 2: Thank you all again for your answers, all of them have been quite informative! :)
If you already have a list, you don't need to parse it – you can simply deconstruct it.
isThisStuff :: [String] -> Query Bool
isThisStuff [c,d] = doesNameBeginWith c <||> doesNameBeginWith d
Then
isMusic = isThisStuff ["MPD:", "ncmpcpp"]
Note that this fails if the supplied list doesn't have exactly two elements.
Arguably, a fold-based solution is better. As you've noted, this can be written
foldr1 (<||>) . map doesNameBeginWith
Now, all you need to do to get rid of doesNameBeginWith
in there is to inline it. Note that
doesNameBeginWith = \str -> fmap ( str `isPrefixOf`) (stringProperty "WM_NAME")
So you can use
foldr1 (<||>) . map (\str -> fmap ( str `isPrefixOf`) (stringProperty "WM_NAME"))
If you don't like the lambda, you can formulate this as a list comprehension:
doesNameBeginWithAny strs = foldr1 (<||>)
[fmap ( str `isPrefixOf`) (stringProperty "WM_NAME") | str <- strs]
Alternatively, you can make doesNameBeginWith
point-free
doesNameBeginWith = \str -> fmap (isPrefixOf str) (stringProperty "WM_NAME")
= \str -> flip fmap (stringProperty "WM_NAME") (isPrefixOf str)
= \str -> flip fmap (stringProperty "WM_NAME") . isPrefixOf $ str
= flip fmap (stringProperty "WM_NAME") . isPrefixOf
= (stringProperty "WM_NAME" `fmap`) . isPrefixOf
so
doesNameBeginWithAny = foldr1 (<||>)
. map ((stringProperty "WM_NAME" `fmap`) . isPrefixOf)
all of this is overly complicated. It gets much simpler when you split up the problem:
stringProperty "WM_NAME"
in the Query
monad.Match any of the supplied strings with it.
doesNameBeginWithAny :: String -> Query Bool
doesNameBeginWithAny prefs = do
wmName <- stringProperty "WM_NAME"
return $ any (`isPrefixOf`wmName) prefs
This can also written with fmap
, as Freerich Raabe showed.