Live data from Hacker News

Why Functional Programming Matters (1984) [pdf]

cse.chalmers.se

61–70 of 145 posts

Re: Why Functional Programming Matters (1984) [pdf]

#61
post #38

Earlier quoted context omitted.

I think he was talking about something like unsafePerformIO. There are plenty of tricks you can not write on pure monads, and there are many Haskell libs that use the unsafePerformIO trick too.

> There are plenty of tricks you can not write on pure monads This made me curious, could you list some?

Anything that needs rewriting a memory address without losing time by allocation and garbage collection.

Handling IO exceptions and masking them as different errors.

Thread, process, or machine coordination in parallel execution.

Re: Why Functional Programming Matters (1984) [pdf]

#62

A lot of pleas for functional programming give a long list of convincing examples that work well with functional programming. You can do this with almost any language, and this is also quite deceptional, as this is often done to convince beginners to learn another language; "look at how simple it is to program this contrived example in !". In order to be able to use a programming language or paradigm well, it is espe…

-- Functional programming does not work well in programs which handle a lot of states Apache Spark is written in Scala. It can handle extremely large amounts of state across large clusters of machines. Is the argument here that Scala is not purely functional? Or what am I missing?

I haven't taken a look at the Spark codebase, but it is very easy to write Scala code that is not purely functional.

Re: Why Functional Programming Matters (1984) [pdf]

#63
post #35

Earlier quoted context omitted.

> As for performance and memory usage: it is always a property of the architecture or system, not of the programming language. Dropping to a low-level language, such as C, usually doesn't buy you too much these days. What is more important is that most C compilers in use have vastly more time invested into optimizing routines than the typical FP compiler. Apart from that, you can easily mange the same kind of data in…

And it's not just about linked lists vs arrays, but also about the actual call stack. FP code tends to be heavy on recursive algorithms, which means you need mutually tail recursive functions. And laziness. Somebody mentioned the State monad and the IO type. Well, these are lazy abstractions with a memory-safe bind/flatMap operation that makes them tick. Well, the problem with these abstractions is that they'll requi…

Saying that Clojure and Scala don't do tail call optimization because of the JVM could be a little misleading. The JVM is a pretty general compilation target, I'm sure you could implement tail call optimization in a compiler targeting the JVM in any of the usual ways. If Clojure and Scala don't do it it must be for some other reason. If I had to guess I'd say it's probably (1) that the developers don't think TCO is that important (lots of language implementations don't have it and are perfectly usable), (2) for ease of implementation, (3) for better interop with Java libraries, or a mix of these reasons.

Re: Why Functional Programming Matters (1984) [pdf]

#64

Earlier quoted context omitted.

And it's not just about linked lists vs arrays, but also about the actual call stack. FP code tends to be heavy on recursive algorithms, which means you need mutually tail recursive functions. And laziness. Somebody mentioned the State monad and the IO type. Well, these are lazy abstractions with a memory-safe bind/flatMap operation that makes them tick. Well, the problem with these abstractions is that they'll requi…

It appears that your claim "Scala or Clojure that don't have real tail recursion because of the JVM" is in error. http://stackoverflow.com/questions/1677419/does-scala-suppor... http://clojure.org/reference/special_forms#recur

As your own link makes clear, Scala does not have real tail recursion because of the JVM. It has a very limited form of tail recursion.

Re: Why Functional Programming Matters (1984) [pdf]

#65

This essay is as much an apology for Miranda and Haskell style lazy-by-default evaluation as it is for functional programming itself, and it's therefore absurd that in 2016 it's still being posted here, let alone enthusiastically upvoted. Lazy-by-default evaluation is a bad idea. It makes the design of the compiler orders of magnitude more complicated (see GHC) and in practice results in nasty performance-related bug…

Framing this essay as apologia for Haskell's laziness is a weird because Haskell was created exactly because there was a proliferation of non-strict functional languages and the Haskell committee recognized that having a common language would be beneficial. So it seems disingenous to separate Haskell and laziness: the latter partly defines the former.

Haskell's evaluation strategy is not something you can just change and have the rest of the language stay the same. If Haskell were strict there would be a good chance that it wouldn't be pure (see: ML variants); if it wasn't pure then IO would not be a problem; if IO wasn't a problem then Phil Wadler wouldn't have needed to invent typeclasses, etc.

Re: Why Functional Programming Matters (1984) [pdf]

#66

Earlier quoted context omitted.

> The main gate to functional languages participating in, say, the Linux kernel is NOT that they are "too slow" or that "laziness makes them too confusing". It's that the Linux kernel is written entirely around the unique weirdness and expectations of C, and only languages based on or descendant to C do well there. Sure, but the usual functional style has intrinsic issues that prevent it from being feasible for writi…

> Sure, but the usual functional style has intrinsic issues that prevent it from being feasible for writing kernels in general. Not really? > A kernel (especially a microkernel) spends most of its time managing state. So does every computer program though. The idea that functional languages can't support mutation is a strangely persistent myth even in the face of multiple counter-examples AND 20 years of improvement…

My point is not that functional languages can't support mutation, I'm well aware of the whole gamut from State to F-Star, Eff, and Idris. My point is that you're going to spend almost all of your time explicitly mutating things, using whatever functional language as a "very fine imperative language."

Yes, you can embed those semantics inside functional semantics, and even use the functional language to add more static verification at the type level via things like F-Star's Hoare logic. But you're still mostly going to shoving bits in specific places based on the result of a shallow pure function applied to bits you yanked from a specific place.

On top of that, you're not going to be able to abide the kind of allocations that functions in Haskell, OCaml, etc. can do with little provocation (and which are hard to avoid categorically), so you'll need to work within an especially restrictive DSL. Definitely no lambdas or partial application. So in the end you'll be in "Generic Stack-focused Pointer-pushing Procedural Imperative Language: The Monad". Where in this do you see any functional-ness, outside of the fact that you'll probably call your procedures functions?

> Many useful & powerful functional abstractions can be written to use constant space, even in Haskell.

Yes, but not to the degree that Atom's use cases require (where the program must allocate all memory ahead of time and therefore know a specific upper bound). This necessitates deviation from usual practices of any kind, including Haskell's.

Re: Why Functional Programming Matters (1984) [pdf]

#67

A lot of pleas for functional programming give a long list of convincing examples that work well with functional programming. You can do this with almost any language, and this is also quite deceptional, as this is often done to convince beginners to learn another language; "look at how simple it is to program this contrived example in !". In order to be able to use a programming language or paradigm well, it is espe…

> Functional programming does not work well in programs which handle a lot of states. It does not work well in programs which have high requirements for performance or memory. It does not work well for programs which have to do low-level stuff.

None of this is true. This is just the generic set of plausible-sounding but meaningless complaints people who haven't actually used FP for any of these purposes tend to repeat.

> a lot of states

What is this supposed to mean? ADTs are by far the best tool for state management available in programming today, and yet there are very few non-functional languages that support them. Languages like Haskell offer extremely powerful tools for state management like monad transformers and ADT-based exception management.

> high requirements for performance or memory

This is an old meme that doesn't apply at all anymore. Haskell has a number of world-class packed data management tools (repa, vector, bytestring, etc.) that can actually do a ton of cool optimizations that a similar library in e.g. C++ could not do. Any marginal overhead incurred by using a functional style (which you are not obligated to use) are typically more than offset by the fact that high-efficiency techniques that are typically inconvenient to represent (like cache-sized chunked text management) are extremely easy to use with strong enough types and flexible enough combinators. For example, if you're doing streaming text management, you can get higher performance in C than Haskell, but it's going to take 100x more effort over just using lazy ByteStrings. Tight numerical code will get unpacked and turned into more or less C-equivalent assembly.

> low-level stuff.

I'm not sure what your definition of "low-level" is. For me it's doing register operations on microcontrollers, and in that case I agree. But for anything you can do on Linux, you are incorrect. Haskell has better low-level support via FFI mechanisms than, say, Java.

Re: Why Functional Programming Matters (1984) [pdf]

#68

Earlier quoted context omitted.

And it's not just about linked lists vs arrays, but also about the actual call stack. FP code tends to be heavy on recursive algorithms, which means you need mutually tail recursive functions. And laziness. Somebody mentioned the State monad and the IO type. Well, these are lazy abstractions with a memory-safe bind/flatMap operation that makes them tick. Well, the problem with these abstractions is that they'll requi…

Saying that Clojure and Scala don't do tail call optimization because of the JVM could be a little misleading. The JVM is a pretty general compilation target, I'm sure you could implement tail call optimization in a compiler targeting the JVM in any of the usual ways. If Clojure and Scala don't do it it must be for some other reason. If I had to guess I'd say it's probably (1) that the developers don't think TCO is t…

You can implement tail recursion optimization on top of the JVM (which is far, far away from a general compilation target BTW), where the distinction is that the function may only call itself. These cases can always be trivially rewritten into loops, and I know at least Scala does this just fine.

More generally tail call optimization allows you to avoid pushing a stack frame for any call in tail position. The JVM (or even LLVM) does not give you the necessary tools to implement this yourself, since you can't play games with your stack frame and return address directly.

Re: Why Functional Programming Matters (1984) [pdf]

#69

Earlier quoted context omitted.

> In order to be able to use a programming language or paradigm well, it is especially useful to know what its weaknesses are. Functional programming does not work well in programs which handle a lot of states. It does not work well in programs which have high requirements for performance or memory. It does not work well for programs which have to do low-level stuff. By the same token, whenever this conversation come…

> The main gate to functional languages participating in, say, the Linux kernel is NOT that they are "too slow" or that "laziness makes them too confusing". It's that the Linux kernel is written entirely around the unique weirdness and expectations of C, and only languages based on or descendant to C do well there. Sure, but the usual functional style has intrinsic issues that prevent it from being feasible for writi…

Does COGENT look functional or imperative in programming style to you? Genuine question as I don't do FP. COGENT is latest in attempts at bringing functional, verified languages into system space. A team already redid the ext2 filesystem with it.

https://ts.data61.csiro.au/projects/TS/cogent.pml

Re: Why Functional Programming Matters (1984) [pdf]

#70
post #23

Earlier quoted context omitted.

Yes. You can model state easily in functional programming languages but the technique is unfamiliar to imperative programmers since it's more explicit. This is a very good thing.

More explicit? Try more convoluted. Ever try to build an event-driven FSM in Haskell? I've seen several try, including myself...the results of which have all been complexity disasters. Imperative languages in general have poor data structures for representing state (no ADTs!), but nothing is more explicit and straightforward than using mutable data or mutable containers for modeling actual mutable state. That's why l…

I don't do FP or Haskell but did do FSM's in imperative languages. Looking up Haskell's event-driven FSM's...

https://wiki.haskell.org/Real_World_Applications/Event_Drive...

https://accu.org/index.php/journals/2199

...gives me code that looks weird since I did imperative but straight-forward. The second link even shows some simplicity and less tangling vs imperative examples. I wonder what makes you think FSM's in Haskell turn into disasters if these examples were so easy.

Besides, you shouldn't be hand-coding FSM's to begin with. The various sub-fields of programming and IT I've studied all came from different directions to same best practice for FSM's: DSL's that generate them. LISP people did it forever. iMatix did it for reliable, distributed apps in C. Haskell embeddings go from stuff like that up to hard real-time C. Theres also open-source projects that compile easy descriptions of them to about any language. The DSL can be included in repo right next to resultant code for documentation purposes. Hardware designers also synthesize and transform them with automated tools.

Given that, the difficulty of doing FSM's by hand should never be a problem for any language. Just don't do it by hand. Automate the tedious stuff machines are good at. Hand-code the stuff humans are good at.

Post reply on HN