A few times FizzBuzz appeared on HN, I made this point ...
> "Outputting fizzbuzz should be done by executing the (one and only) piece of code that outputs fizz, followed by the (one and only) piece that outputs buzz. That is because fizzing and buzzing are two separate activities – consider the FizzBuzzHissHowl problem, where hiss and howl are printed for multiples of 7 and 11 respectively. The program design of Exhibit A and B would lead to an explosion of code complexity."
... but always got voted off the island in favor of Exhibit A.
Unclear to me why the canonically correct answer examples for various languages are almost universally mistaken as described there, and yet so fiercely defended!
Perhaps Exhibit C is like Fight Club, to be kept hush hush as a shibboleth for sussing out Principal Engineers?
fizzbuzz n = (test 3 "fizz" . test 5 "buzz") id (show n) where
test d s x = if n `mod` d == 0 then const (s ++ x "") else x
main = mapM_ (putStrLn . fizzbuzz) [0..100]
I think a major part of the FizzBuzz test is writing something simple and understandable. Premature/unnecessary optimization isn't a plus, it's a minus. Start with the basic "Exhibit A" for a FizzBuzz.
If a second problem asks you to write something for "FizzBuzzHissHowl", then you can start introducing more code complexity.
As a novice ( but really interested) in functional programming, I had a bit of troubles with Haskell and eventually didn't find something I could do to toy with it.
This paper is basically what I want to try doing in functional programming : almost write maths, but that does the computation.
It wasn't too complex either !
Can someone point me to other resources in the same genre ?
I know this is a "toy" paper, but is enough to reason as to why few use Haskell in production (ignoring the tooling issue). It's pretty gnarly even for a basic problem.
I didn't realise utilising HoF meant rolling your own interpreter ;).
Pure FP is very interesting, but having to write entirely without side-effects would be a real challenge for me. I use js+ramda[0], we effectively write our services as a `pipe`, you just stick in transforming fns whereever you need to, e.g.:
const handler = pipe(
fn1,
fn2,
fn3
)(event)
The underlying implementation of `fn1` for example doesn't need to be written in an fp paradigm, it can be written imperatively. You could then slowly-slowly chop out the imperative functions for fp ones if you really wanted, but IMHO some problems are best solved imperatively.
My advice is instead: "Programmers! Remember to use the right tool for the job!"
You're looking at this the wrong way. The paper isn't showing Haskell is gnarly for a basic problem, it's using a basic problem to demonstrate a particular technique that you can use in Haskell. There are plenty of simpler ways to implement this kind of thing in Haskell, and even some that are both simpler and show off some of the more unique features of Haskell. The goal here wasn't "let's find the best way to write fizzbuzz in Haskell", it was "let's show off how to build an interpreter to solve problems, using a small problem everyone is familiar with".
Haskell isn't ill-suited for something like fizzbuzz at all, it's just _also_ suited for things like quickly writing interpreters and solving problems that way when it makes sense.
I find a lot of people don't get pedagogy. They want immediate, authoritative statements on what is good or bad. Haskell isn't really about that. It's about the 10s of equivalent ways to solve every simple problem. That's what makes it fun. And fun is Haskell's secret sauce.
> Haskell is simple even if unfamiliar to you. Brainfuck is complex even if familiar to you.
I would actually swap these two descriptions. Haskell is complex, because it has many "complications" (in the sense of features). But those complications permit simple programs. Brainfuck is simple, it has few complications (only 8 instructions) but this forces complications into the programs written in it.
Simplicity is not merely measured in the "number of things" you have, it's contextual. Otherwise we'd all be writing in binary representations because base two is the simplest way to communicate information.
Simplicity is also "how many things" it takes to express an idea or do a useful thing.
In many ways, written Chinese is simpler than written English.
I don't like that solution very much because of the 4 cases, or generally n*2 cases if there are n tokens. My favorite Haskell solution uses monoids (specificaly the Monoid instance of Maybe String) and is quite natural in Haskell but would take some explanation for non-Haskellers.
My version looks like the below. I didn't originate the approach but I like this spelling. It won't make total sense to non-Haskellers though.
{-# LANGUAGE MonadComprehensions #-}
import Data.Maybe
import Data.Monoid
fizz :: Int -> String
fizz n = fromMaybe (show n) $ f 3 "Fizz" <> f 5 "Buzz"
where
f :: Int -> String -> Maybe String
f d msg = [msg | n`rem`d == 0]
main = mapM_ putStrLn [fizz n | n <- [1..100]]
This extends in an obvious way to FizzBuzzHissHowl, lets the Monoid instance manage concatenating the special tokens together while remembering if any of the rules have matched, and uses a monad comprehension on the Maybe monad to cleanly lift the token into the Maybe monad if the number is a multiple of whatever. The type annotation on f is added to make it a little bit clearer what is going on.
The use of monoids and the monad comprehension may be slightly flashy, but the use of Maybe to remember whether a rule has triggered is second nature in Haskell.
This is not too dissimilar to the final solution outlined in the essay, but is much more readable, in my opinion, due to its use of mappend over Maybe Strings instead of implementing the same sort of compositionality using regular function composition. Very elegant!
The one you linked is close to how you'd write this in idiomatic Haskell. The paper is describing a particular technique, and using FizzBuzz as an example problem, not suggesting that the technique is a good way to solve FizzBuzz.
So, instead of checking twice if the number is divisible by five, you check once but then you check the type of every instruction again. How is that a win?
Yeah it is a bit of a strawman, especially as Exhibit B solves this problem (and an inline function would remove the duplication). However as the mention at the end this isn't a serious performance tuning session, or even a serious answer to FizzBuzz, but a way to introduce some Haskell concepts.
Ugh. There are languages that encourage this kind of time wasting. Avoid them. Also,
> Exhibit A, in some cases, performs the ‘mod‘ 3 and ‘mod‘ 5 tests more than once
Isn't Haskell a language with controlled side-effects? Compiler ought to see that the same operation is performed twice and factor it out. There are no mutable variables in the scope.
<https://codegolf.stackexchange.com/questions/215216/high-thr...>
<https://github.com/orent/htfizzbuzz/blob/master/fizzbuzz.S>