Feb 26 2008
My shame is complete
module Main where import Data.Maybe fizz = concat $ repeat $ replicate 2 Nothing ++ [Just "Fizz"] buzz = concat $ repeat $ replicate 4 Nothing ++ [Just "Buzz"] fizzbuzz = zipWith (maybeWith (++)) fizz buzz numbers = map (Just . show) [1..] maybeWith f (Just a) (Just b) = Just (a `f` b) maybeWith _ (Just a) Nothing = Just a maybeWith _ Nothing (Just b) = Just b maybeWith _ Nothing Nothing = Nothing -- an infinite list of fizzbuzzes results = map fromJust $ zipWith (maybeWith const) fizzbuzz numbers
I bothered posting this at all because I feel sure that maybeWith can be implemented as a simple combination of other functions. It’s sort of like liftM2, except it doesn’t throw away good values when it has one good and one bad.
Also, I used it twice in five lines, so it surely must be a known function. But for the life of me I can’t think what it could be.
What the hell? There’s no way I’m accepting this.
I want a solution with Monad Transformers and Arrows.
What are they teaching you kids these days?
What about (untested):
…there’s supposed to be backquotes around the “mplus”. Might be nice to have a preview feature.
Well, Robert, you could look at the “main1” version at http://hpaste.org/5934 to see “ContT IO” used. And using a new Monoid in main2 and main3 is one of my favorite styles. It combines the separate Fizz and Buzz specifications to solve the problem. So adding new rules that combine in the same way is trivial. And they all should scale well to large numbers.
@Greg:
Yep, you’re right. That works perfectly. (I fixed the formatting for you. The comments use Markdown syntax for future reference.)
@Chris:
That looks pretty interesting. I still don’t have a proper understanding of continuation use but I can see the gist of your solution.
You made programming.reddit!
Yeah Rob, it’s a wee bit embarrassing considering the less-than-intellectually-heavyweight subject of this post. ;-)
I wish I understood these replies, but I can tell tell it’s exciting stuff
Seeing
Maybe aas the a finite map (container) with only one possible key (think ofData.Map () a), the canonical name formaybeWithwould beunionWith. This doesn’t conceptually fit into Monad or MonadPlus, so I don’t know a really short way to get it from there.However, the cases
maybeWith (++)andmaybeWith constare special. The latter is the monoid operation onMaybe [a]and the latter ismplus. (It can be debated whether the Monoid instance is wrong in the sense that we should havemappend = mplus.) In other words, we havemaybeWith (++) = mappend maybeWith const = mplus
And to avoid the potentially “unsafe” call to
fromJust(could raise an exception), we can appeal tox
mplusJust y = fromMaybe y xPutting everything together, we get the solution
I had a similar version which I posted shortly after I saw this… it doesn’t seem to have shown up in the trackbacks for this post, so I’ll link it manually :)
My version.