3 ms·
I 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 k
by Shish2k 13y ago
I 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 13y agoMy guess is that this comes from the math culture where single letter variables are the norm.
- kazagistar 13y 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 13y 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).
- Shish2k 13y agoIn the case of folding at least, I think there is a function, a value, and a collection -- personally I'd call them something like "func", "val", and "list" rather than "f", "z" and "t" -- still very generic, but not completely generic (though perhaps in haskell, functions, values, and collections are interchangeable? I can't imagine how that would work though, if you pass a collection in as the first parameter to foldr...)
- ufo 13y agoThere are some single letter names that are kind of standardized and don't get better with longer names, kind of like i, j and k. For example, f and g will usually stand for functions, a and b in a type signature will usually stand for some opaque "value" type and x and y will be used to refer to variables of these types. xs is a list of x and m usually stands for monad something (`m a` is a monadic type, mapM is the version of map for monads, etc). Going back to the foldr example, its actually not that bad. The f is already clearly a function (from name and type) and the full type of foldr is [1] foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b so you actually are told what the `t` is (its a Foldable). I could see them using `zero` instead of `z` but its a 3 line function that does what you would expect from the name so its not that big of a deal. TBH, the bigger problem is having a folding abstraction in the first place. If no one ever teaches you about it, its hard to get the point just by reading the source code but once you know about what a fold is you don't need to actually look inside the implementation that much. That said, there are cases where I do think that longer variable names would help a bit. For example, you might come across types with 5 or 6 type parameters like [2] data Pipe l i o u m r and I think in these cases the more descriptive names like in [3] newtype Form m input error view proof a might help a bit. Its still a tradeoff though - types get harder to read if they get too long and types show up all over the place so they tend to need shorter names than variables. [1] http://www.haskell.org/hoogle/?hoogle=foldr http://www.haskell.org/hoogle/?hoogle=foldr [2] http://hackage.haskell.org/package/conduit-0.5.0/docs/Data-Conduit.html#g:3 http://hackage.haskell.org/package/conduit-0.5.0/docs/Data-C... [3] http://www.happstack.com/docs/reform-0.1.1/doc/html/reform/Text-Reform-Core.html#g:3 http://www.happstack.com/docs/reform-0.1.1/doc/html/reform/T...