3 ms·
I felt the same way (and still do in general, with notable exceptions). I.e. to put this first: I think a lot of the Haskell community is obsessed with mathemat
by wirrbel 11y ago
I felt the same way (and still do in general, with notable exceptions). I.e. to put this first: I think a lot of the Haskell community is obsessed with mathematical "cuteness", which basically they take to mean "infix-operator-heavy" notation.
Nevertheless, I have learned to like some operators,
<$> <*>, *>, <*
are ones that come to my mind. The operator
<$>
is basically fmap as infix notation, so `fmap f [1,2,3]` would be `f <$> [1,2,3]`. This makes mapping as easy as a normal function call (and the operator name `<$>` was not choosen arbitrarily. `$` by itsself is the function application operator, so `f $ 3` does on a single element, what `f <$> x` maps over an instance of Functor.
With applicatives, the pattern of
f <$> a <*> b <*> c
is very common (with a type signature
f :: a -> b -> c -> ....
- JadeNB 11y agoI think that your second indented block, which is currently <*> , is supposed to be `<$>` (based on the rest of your discussion).
- spion 11y agoYes, <$> is the general `map` (`fmap`) <*> takes function(s) out of a mappable and applies it (them) to argument(s) within a mappable. (+) <$> [1,2,3] = [add 1, add 2, add 3] (+) <$> [1,2,3] <*> [10, 20] = [(1 +), (2 +), (3 +)] <*> [10, 20] = [11, 21, 12, 22, 13, 23] (+) <$> Just 3 <*> Just 5 = Just (3 + ) <*> Just 5 = Just 8 (+) <$> readLn <*> readLn = ... well that depends on the inputs :)
- wirrbel 11y agoindeed, fixed it, thx.
- akavel 11y agoNow that is the first time I see an explanation which tries to point out some sense in the apparent madness. Appreciated! Would you or someone else knowledgeable be willing to create a guide like this, but spanning all the magic runic incantations known to Haskell wizards? Showing similarities, analogies, etc? And targeted at dumb apprentices like me? I'd be happy to serve as a somewhat (though not perfectly) dumb specimen to bounce explanation attempts off! (email in my profile - just added, in case someone was crazy enough to try to pull that off)
- davesque 11y agoIt's nice that someone was trying to make things sensible. But what are the precedences of those operators? Maybe you would argue that you can expect them to be whatever makes the most sense. But what about the one case when they aren't what you expect and you're getting some confusing error (or, gasp, incorrect runtime behavior). Maybe a library designer made a bad decision about which precedence to give to a certain operator. Or maybe the choice was simply not so obvious. I guess the solution is just to put parentheses everywhere, but why is it that, whenever I show people code where I'm doing that, they always point out "Oh, you don't need parentheses there." I feel like that just goes to show that the community underestimates the confusion most people feel when they encounter a jumble of custom operators and have to recall to themselves which parts of an expression are evaluated first or even in what direction. This language feature feels more like an antipattern. I really think the benefits of making operators so easy to define are quickly outweighed by the drawbacks for most programmers. The infix culture seems like one of the biggest barriers for this language.
- wirrbel 11y agoI concur with your uneasines about operators, I often find them used "too often" in Haskell, I have been a Clojure/Scheme guy in the past. But: For Functors and Applicatives for example, they do make sense. If you are using them, you can use them in any program you write. Just like we found addition and multiplication with numbers build an abelian group and chose to represent these operations by "+" and "-" (with the difference that in Haskell Programs, Functor-capable data structures pop up everywhere). So that being sad about the motivational level, I would like to address some of your arguments against operators on the syntax level. Precendence can be a problem and obviously it is something that is and has to be learned and might confuse beginners. Nevertheless, Haskell's typechecker will often tell you when you missed up. I started of parenthesizing the hell out of these expressions and let hlint tell me when I could remove the parens, after a few days I hardly made any of these mistakes anymore. While - as a Lisp guy - i do prefer functions over operators quite a bit, it is not like it is a terribly difficult thing. People have committed to learn inheritance, and multiple inheritance. Write classes where the hold and manage a lot of state and let that state interact, etc. That stuff is magnitudes more complicated than Haskell operators, already on a conceptional level.
- pandaman 11y agoIt helps to read $ as "value". Then "function $ x" is "function value (of/at) x". Works in some other languages too, e.g. $VARNAME = value (of) VARNAME.