4 ms·
Thank you, I found this very helpful. I'm being selfish, but I'd love some more examples like this where you compare the basics in Haskell against more mainstre
by arms 12y ago
Thank you, I found this very helpful. I'm being selfish, but I'd love some more examples like this where you compare the basics in Haskell against more mainstream, imperative languages - it makes it easier to digest.
- kazagistar 12y agoUnfortunately, the semantics get even more different from there. Its like learning to speak a new language, the faster you stop trying to translate things in your head, and just understand them directly, the easier it is. For example, this is the default implementation of foldr, in the Traversable typeclass, in terms of a foldMap implementation: foldr :: (a -> b -> b) -> b -> t a -> b foldr f z t = appEndo (foldMap (Endo . f) t) z This does not take long to grok in Haskell, but translating it to any imperative language would make no sense. It requires an understanding of the semantics of Monoids, currying, function application, and Endofunctors. None of these are hard, but none of them exist in more mainstream imperative languages. But heck, this is at least something like what it is doing: #!python3 from functools import partial def foldr(f, z, t): for endo in (partial(f, i) for i in t): z = endo(z) return z Only, um, not quite, because iterables are not exactly foldables, it lacks the generality of actually calling the foldMap function (which can be different in different types), it has no type signatures so it is less strict about its parameter, and this is cheating a bit because python already has nice functional programming tooling compared to many other languages, and so on. But the jist is there, and even some of the performance qualities of lazyness if you get how iterators work in python. I personally suggest you just learn it from scratch. Its not just a different skin over the same ideas, like so many other languages.
- Shish2k 12y agoI think my main beef with haskell isn't the syntax per se, but the culture of single-letter variable names, which this post so wonderfully demonstrates :P (I know this is just a short demo rather than production code, but all the "good examples of haskell" I saw at university were like that too, and much of the online documentation I saw :/ )
- rhizome31 12y agoMy guess is that this comes from the math culture where single letter variables are the norm.
- kazagistar 12y agoI was a bit unnerved by the single variable names as well. But frankly, using full world variables adds little actual clarity in most cases where they are used. What the variables are is clear from the types, and what the types are is usually stated very clearly within a few lines, barely a glance away for reference. I will concede however that the python example could use variable names for clarity, since no such types are stated nearby. I have found that long variable names don't help, and sometimes even hinder my understanding of haskell code. foldRight :: (accum -> item -> item) -> accum -> foldable item -> accum foldRight combiner initialAccum foldables = appEndo (foldMap (Endo . combiner) foldables) initialAccum ... that didn't help. After all, each variable was used once, and there were only 3 variables in the entire scope. Most functions are like that, and you can easily keep track of it without breaking a sweat. What is important to keep track of is what types those are, and what functions are valid for those types, and how those types are changed with function application and whatnot. So its not just because of the test example. I actually copied and pasted the original out of the standard library, so it is about as canonical as it gets. The best possible description for f is (a -> b -> b), and while you might hand wave it as a "combiner" or "accumulationStep" or whatnot, that does almost nothing to clarify how this function works. The cultural choice is not arbitrary. The real cultural difference is in the level of abstraction so often being "above" the semantics. In java, or python, or whatever else, I will religiously use nice, expressive names. But the short names, and other even crazier things like pointfree syntax actually feel somewhat more natural in Haskell.
- rlpb 12y agoThe problem is that the functions are so abstract, the variables barely have any meaning. They could be almost anything, so there aren't really any obvious names to give them. I think this is what makes Haskell so difficult initially. Everything is abstracted to the extreme. Explanations must either stick to the abstractions (making it difficult to grasp), or give concrete examples (necessarily limiting the scope of what is learnt).