4 ms·
They actually don't precalculate, since Haskell is lazy. This kind of construction of the infinite data structure and relying on laziness is a really typical tr
by madhadron 7y ago
They actually don't precalculate, since Haskell is lazy. This kind of construction of the infinite data structure and relying on laziness is a really typical trick in Haskell. For example:
fib = 0 : 1 : zipWith (+) fib (tail fib)
Indeed, the way the author has written it would seem a little strange to most Haskell programmers, I think, who would just write (in this idiom):
mapIdx f xs = map (uncurry f) $ zip [1..] xs
fizz = ["", "", "Fizz"] ++ fizz
buzz = ["", "", "", "", "Buzz"] ++ buzz
fizzBuzz = mapIdx f fbs
where f n "" = show n
f _ v = v
fbs = zipWith (++) fizz buzz
main = mapM_ putStrLn $ take 100 $ fizzBuzz
Though usually you would just write it a more typical way
f :: Int -> String
f x | x `mod` 3 == 0 && x `mod` 5 == 0 = "FizzBuzz"
| x `mod` 3 == 0 = "Fizz"
| x `mod` 5 == 0 = "Buzz"
| otherwise = show x
main :: IO ()
main = mapM_ (putStrLn . f) [1..100]
But, yes, I don't find the semigroup connection particularly illuminating.
- bawolff 7y ago> They actually don't precalculate, since Haskell is lazy. I mean they ditectly put into the source code that the pattern is "", "", "fizz", etc..., and repeat (in a lazy fashion), instead of having the computer calculate which integers give a fizz/buzz. So the programmer is in a sense precalculating at the time of writing the program, instead of having the computer calculate the result of the if statements at runtime.
- chongli 7y agoThey’re only doing it once though, not for every multiple of 3 or 5. So if you didn’t like the line: buzzes = cycle [Nothing, Nothing, Nothing, Nothing, Just "Buzz"] You could instead write: buzzes = cycle $ replicate 4 Nothing <> [Just “buzz”] It’s not a big difference though. Since everything is lazily evaluated, you’re not precalculating anything.
- bawolff 7y agoI think you misunderstand what i mean by "precalculated". I just mean the answer is embeded in the source code and not calculated at runtime. It doesnt matter how you embed it in the source code, whether that is a list literal or constructed via functions or whatever Edit: for clarity, the reason i think this is kind of a cop out, is that in the article the author seems to call out not using if-then-else as a benefit of this solution, compared to the normal version that takes a list of integers and transforms it using if/then/else and mod operations. But i dont really think it counts as not using if/then/else if you literally do the same operation in your head and then just write down the transformed list explicitly, to save the computer the effort of transforming the list at runtime for you.
- chongli 7y agoIt would be pretty straightforward to parametrize those functions so you could fizz buzz on any numbers, not just 3 and 5. Or is that not what you meant? You want a system that can solve any problem? Then you’re looking at a computer algebra system. SageMath [1] is a nice one. [1] https://www.sagemath.org/ https://www.sagemath.org/
- inimino 7y agoI think what you are trying to say is that it's not using the modulo operator to derive the pattern from the integers, instead it is simply encoding the pattern directly in the program as a pattern (false, false, true, ...). Your objection is confusing everyone else because these are both equally "calculations", and the meaning of the "divided evenly by three" calculation and the meaning of the FFTFFTFFT... sequence are the same, so it just two ways of expressing the same thing. Either way is just as "precalculated" as the other.
- inimino 7y agoAnother way to put it is that `x % 3 == 0` and `cycle [0,0,1]` are just two forms of shorthand for the same concept.
- chongli 7y agoYes, exactly. In group theory when we speak of a quotient group modulo one of its normal subgroups, we’re referring to exactly this. Z3, the integers mod 3, is isomorphic to (actually equal to) Z/3Z, the integers quotiented by all the multiples of 3. People who haven’t studied abstract algebra aren’t used to thinking of it this way though. To most people, the modulus operator is specifically an operator that returns the remainder of Euclidean division. To think of it as a bunch of equivalence classes that split up the integers is not something most people think of right away.