Skip to content

Instantly share code, notes, and snippets.

@missingfaktor
Created September 17, 2011 08:59
Show Gist options
  • Select an option

  • Save missingfaktor/1223770 to your computer and use it in GitHub Desktop.

Select an option

Save missingfaktor/1223770 to your computer and use it in GitHub Desktop.
A simple problem solved in Haskell
import Data.Maybe
lengths :: (Int -> Bool) -> [[a]] -> [Int]
lengths pred xs = mapMaybe lengthIfLong xs
where
lengthIfLong s = let n = length s
in if pred n
then Just n
else Nothing
main =
print $ lengths (3 <) ["hello", "k", "baby"]
@md2perpe
Copy link

    main = print $ filter (3 <) $ map length ["hello", "k", "baby"]

@missingfaktor
Copy link
Author

@md2perpe: The puzzle was posted at [scala-user] mailing list, and the constraint was that the the result must be obtained in a single pass. So the solution with map and filter (which is the most obvious solution here) was not allowed.

@md2perpe
Copy link

Actually, thanks to Haskell's laziness, this is done in a single pass.

@missingfaktor
Copy link
Author

@md2perpe: Yes, I am aware of it. With Scala, one has to first invoke .view on list to make it a single pass operation. What I was trying to achieve was to obtain the result with a single collection operation. So I first headed to Hoogle, and searched for [a] -> (a -> b) -> (a -> Bool) -> [b], but didn't find anything useful. Next, I tried [a] -> (a -> Maybe b) -> [b] and landed at mapMaybe. And so I used that. :-) To my dismay, neither Scala stdlib nor Scalaz has this function.

@md2perpe
Copy link

At some occasions I've declared a function justIf:

    justIf :: (a -> Bool) -> a -> Maybe a
    justIf p x = if p x then Just x else Nothing

With that one you could write

    main = print $ mapMaybe (justIf (3 <) . length) ["hello", "k", "baby"]

I really miss justIf in Prelude or Data.Maybe.

@missingfaktor
Copy link
Author

@md2perpe: +1. IMO it's common enough a case to deserve an inclusion in Prelude.

By the way, what do you think about this solution?

main = print $ mapMaybe (mfilter (3 <) . Just . length) ["hello", "k", "baby"]

@md2perpe
Copy link

Nice. You rewrote my last solution using already defined functions.

Thus, justIf p = mfilter p . Just.

@missingfaktor
Copy link
Author

@md2perpe: We can go one step further, and make it point-free. :-)

justIf = (. Just) . mfilter

@md2perpe
Copy link

Oh... :-D

@md2perpe
Copy link

A question about markup...

How do you get the code blocks in your comments to be syntax colored?

@missingfaktor
Copy link
Author

@md2perpe: See "syntax highlighting" section here: http://github.github.com/github-flavored-markdown/.

@md2perpe
Copy link

Ah, I recognize that. My eyes have seen it, but my brain hasn't memorized it.
Testing:

justIf = (. Just) . mfilter

Updated my earlier posts to have syntax highlightning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment