4 ms·
First I would like to say that I am only learning Haskell, and have done nothing but toy programs thus far. But the point free style is something that I really
by hristov 17y ago
First I would like to say that I am only learning Haskell, and have done nothing but toy programs thus far. But the point free style is something that I really do not like about Haskell. It makes code much more complicated for the dubious benefit of saving a couple of keystrokes.
For example, take the code from the article:
This is without point free style:
sum xs = foldr (+) 0 xs
And this is with:
sum = foldr (+) 0
You have saved a total of 4 keystrokes. And made that line of code look really weird and hard to understand.
Thus, now when you look at code you cannot say at first glance how many arguments a function takes. The second line of code looks like sum takes 0 arguments. But you have to look more carefully at the definition of the function, and see that it uses foldr, and know that foldr takes three arguments, but here only two are defined, and then you figure out that someone is using point free style and then you figure out that sum, actually takes one argument that must be a list.
And this of course, is a simple example. Here we have a big clue in that the function is defined with zero arguments, and most functions take at least one argument, therefore the function probably uses the point free notation. But for a more complex and longer function, the point free style can very easily confuse someone reading the code.
So yeah, I think point free style is one of these annoying features of Haskell, that seem to be put in so that users of Haskell can pat themselves on the back and feel like they are very smart. But in the end it does not add much to the language and makes it much less accessible.
- mbrubeck 17y agoOnce you're used to the idiom, I find point-free style at least as easy to read as pointful. "Thus, now when you look at code you cannot say at first glance how many arguments a function takes." In Haskell I generally look at the type signature - explicit or inferred - to see what a functions' arguments are. I find this style is actually more beneficial for larger-scale examples than smaller ones. For example, if you have a memoizing combinator, most people would not find it odd at all to write: fast_factorial = memoize factorial instead of: fast_factorial xs = (memoize factorial) xs The key to point-free style is to think of all functions as potentially acting like combinators, and being modifiers for other functions.
- hristov 17y agoAnd where do you find the inferred type signature?
- mbrubeck 17y agoI load the module into ghci and use the :t command. But I mostly do this during development. This is the big reason that production-quality code should generally have explicit type signatures for top-level functions.
- Periodic 17y agoIf we're talking about making code easy to read, type signatures are one of the best tools. Many times you can look at the name of a function and its arguments and you have a very good idea of what it does. This is unlike many dynamic languages where the returned value could be an object of just about any class. Are we getting a hash? An array? A custom class? Who knows without reading the details of the function.
- hristov 17y agoWell this kind of proves my point. If you have to compile code simply to read it, then the language is not very easy to read. What if you are reading the code in order to debug it and the code cant compile? And I know code should have type signatures but it often doesn't.
- jrockway 17y agoAnd I know code should have type signatures but it often doesn't. Often? All the libraries in GHC have type signatures. All the libraries on HackageDB I've used have type signatures. All the apps I've written have type signatures. Even most Haskell blog posts (and wiki pages) use type signatures. I think you should just peruse some production Haskell code, and try writing a bit of your own. If you set aside your belief that everyone is out to confuse you for a few minutes, I think you'll find that most Haskell is quite readable, and quite writable. You'll see how other people compose functions, what the idioms are, and then stuff like "sum = foldr1 (+)" won't confuse you anymore. Instead, I think you'll see how you can read and write code more quickly, and how to understand your program in terms of function application instead of in terms of passing around boxes that hold data.
- jrockway 17y agoI think you will get over this after about 3 days of using Haskell for real. It's an essential technique that greatly improves readability once you get used to it. Remember, functional programming is about composing functions (and effects), not about data flowing through the program. Ideally you will never see your data, but sometimes it's easier to mention it. (I thought the same thing; "I hate point-free". But then I started writing serious code, and realized that it's much easier to read when you don't mention the irrelevant.) You have saved a total of 4 keystrokes. And made that line of code look really weird and hard to understand. Anyway, your examples are faulty. Here's what they would look like in real life: Point-ful: sum :: Num a => [a] -> a sum xs = foldr (+) 0 xs Point-free: sum :: Num a => [a] -> a sum = foldr (+) 0 So there is no confusion; there is actually less confusion. Sum is just a fold over (+) with a seed of 0. That's all it is; the fact that there is this "xs" variable is irrelevant -- we know a fold operates on a list already, there is no need to say that again. If the sum example confuses you, that's fine, that's not the best example of point-free style. Perhaps these are easier to understand: Tack on ".xml" to every filename in a list: (++ ".xml") <$> files instead of: (\x -> x ++ ".xml") <$> files Extract the `snd` part of a value during a monadic computation: f >>= return . snd Instead of f >>= \x -> return $ snd x And so on. Basically, point-free style lets you omit the parts that are understood. In the second example, of course you're operating on the value that >>= binds. That's the point of >>=. No need to say that every time. So yeah, I think point free style is one of these annoying features of Haskell, that seem to be put in so that users of Haskell can pat themselves on the back and feel like they are very smart. But in the end it does not add much to the language and makes it much less accessible. Nope, sorry. Point-free notation often makes code simpler and easier to understand (and easier to compose, of course). If it doesn't make your particular code easier to read, then the solution is simple -- don't use it in that case. But it is yet-another useful tool in the toolbox.
- Groxx 17y agoNice examples, I was wondering about this myself (having not done any functional programming). Any suggestions for starting a functional language? And which to start with? I'd love to eventually get really deep into it, but I'm really busy lately and can't devote a lot of time to get my brain over a high hurdle.
- pw0ncakes 17y agoI like point-free when I want to express that I'm creating a function on a function. For example, memoize is a combinator that takes a function and returns another one. So I don't mind seeing (memoize f) as opposed to the sloppier (\x -> (memoize $ f x)). Yet I don't enjoy point-free always. I'd probably be more comfortable with the pointed sum example (although I'd be able to understand either). When there are lots of . and $ floating around, point-free code can be tough to read for the uninitiated. What you do get out of point-free is an appreciation for currying and partial function application, which are crucial if you want to understand the lambda-calculus on which functional programming is based. If you're doing calculations in lambda calculus (in which there's no distinction between first-class "data" values and functions, at least in the untyped version, because all objects are apply-able) you're constantly removing extraneous variables.
- camccann 17y agoSpeaking only for myself, I have to say I actually find your point-free version of "sum" more readable. The extra argument is just visual clutter. Pointless style only gets really confusing when you end up with a bunch of composition operator sections shuffling the order of things around in unclear ways.