News for hackers. Stuff that matters.
Re:Why Haskell is suited to IO by mattdeboard on Monday July 04, 2011 @11:23AM (#2726768)
Here's what I don't get about Haskell's.. philosophy I guess.

(Disclaimer: I've only spent about a week learning me a Haskell for great good, and that was a couple weeks ago, so I'm not an authority by any measure.)

The Haskell community uses the word "pure" a lot, and I don't get it whatsoever. Even this musing says it's "easier to write correct pure code than correct imperative code." What does that mean? Is "pure" code the opposite of "imperative" code?

Re:Why Haskell is suited to IO by mitchellh on Monday July 04, 2011 @11:42AM (#2726805)
So, "pure" is the opposite of "impure" and "lazy" is the opposite of "strict" (but often cited as "imperative). Haskell is a pure, lazy functional programming language. I'll talk about purity here, and not about laziness.

Pure means that functions are not allowed to have side effects. More formally, a pure function can only use its inputs (parameters) to generate its output. Therefore, a pure function can't modify a global variable, print to the screen etc. because those are all side effects (more on this later). The benefit of this is threefold:

* Testing is much safer and generally easier. You just have to test the various inputs and edge cases and you can pretty much guarantee the function is 100% correct. You can't get this guarantee in impure languages.

* Inherently concurrent. Since functions don't modify any global state, you're free to make this as concurrent as you want without worrying about "thread safety" and all that.

* Increased modularity. Pure functions are highly portable, since they don't modify state they can be used for any library if needed, really. In an impure language, you often have to modify functions for use in a more general sense as a library.

Of course, the real world has side effects. Almost every program we run is a side effect, since we're giving it input from the world and it uses that to print to a screen. So how can a program be pure at all???

Without going into too much detail, there are ways in Haskell to isolate impurity to a small part of the code which is clearly marked as impure. This impure code is responsible for say, reading a string from the user input. This string can then be used to make function calls to pure functions.

So the way you do things is to put all your business logic and such in pure functions, then the impure functions just deal with shuttling values to and from the real world. You can test pure functions with theorem checkers and you test impure functions with unit tests and integration tests.

Haskell has a steep learning curve since it has so many concepts which still simply haven't made it into more industry-standard languages. This is getting better with language such as Scala becoming more mainstream.

I really love Haskell and even if I don't use it on my day-to-day, it is great to hack out a Haskell program every once in awhile.

Hope this helps!

- Mitchell

Re:Why Haskell is suited to IO by ankrgyl on Monday July 04, 2011 @11:58AM (#2726850)
Great explanation. Just a small point though,

> "lazy" is the opposite of "imperative."

should be: "lazy" is the opposite of "strict" or "eager". "Imperative", in this context, is the opposite of "functional".

Re:Why Haskell is suited to IO by chc on Monday July 04, 2011 @12:59PM (#2727043)
It's basically impossible to have a lazy imperative language, though, because "a sequence of statements" is the definition of an imperative program, and laziness leaves the ordering of that sequence undefined.
Re:Why Haskell is suited to IO by ankrgyl on Monday July 04, 2011 @01:43PM (#2727207)
Re:Why Haskell is suited to IO by chc on Monday July 04, 2011 @10:01PM (#2728412)
I don't mean to split hairs, but Scala isn't a lazily evaluated language — it's a strict language that allows optional lazy evaluation, and AFAIK it only really works well if you're programming Scala in a more or less functional style. I'm pretty sure Scala's lazy values still lead to unpredictable behavior if you lazy up something that has side effects.
Re:Why Haskell is suited to IO by michaelschade on Monday July 04, 2011 @01:06PM (#2727066)
Essentially implied by what Mitchell has said, but it's good to point out that pure functions have referential transparency, which means that for a given input, the function will always give the same output. (So, `myFunc 7' always yields the same answer), which makes it easier to reason about your code and have more reliable tests against these functions.

More reading here: http://www.haskell.org/haskellwiki/Functional_programming#Pu...

Re:Why Haskell is suited to IO by mattdeboard on Monday July 04, 2011 @01:07PM (#2727075)
Great explanation, actually. But one question. I thought functional languages were "pure" throughout. I mean, I thought the whole point of a functional language is that there are no side effects and every expression returns some value. How is "pure" distinct from "functional"?

edit: BTW, Haskell DOES have a steep learning curve, and the inherent recursion breaks my brain. Even simple things like:

`combos = []` `combos = combos + 'foo'`

hurt, because counterintuitively (to me, anyway) this winds up in infinite recursion. I'm very used to OOP so this sort of thing is hard on me. I'm old though.

edit: I'm a little bummed out by the downvotes on my original question. It was an honest academic question I had and was answered splendidly. I was not attacking Haskell whatsoever. I apologize if anyone took it as anything other than an honest question.

Re:Why Haskell is suited to IO by mitchellh on Monday July 04, 2011 @01:21PM (#2727118)

  Great explanation, actually. But one question. I thought functional languages were "pure" throughout. I mean, I thought the whole point of a functional language is that there are no side effects and every expression returns some value. How is "pure" distinct from "functional"?
Oh, no no. Pure is not required for functional programming. Functional programming is mostly defined as the ability to pass around functions as 1st class data types. In fact, I noticed on your GitHub you do some Python. Here is functional programming in Python:

  # Sum a list in Python using FP
  items = [1,2,3,4,5]
  function = lambda x, y: x + y
  reduce(function, items) # => 15

  # The equivalent in haskell:
  foldr1 (+) [1,2,3,4,5]
Pure is a stricter form of functional programming, which Haskell enforces.

  edit: BTW, Haskell DOES have a steep learning curve, and the inherent recursion breaks my brain. Even simple things like:
  `combos = []` `combos = combos + 'foo'`
  hurt, because counterintuitively (to me, anyway) this winds up in infinite recursion. I'm very used to OOP so this sort of thing is hard on me. I'm old though.
You're stepping now into the "lazy" aspect of Haskell. You're allowed to have infinite recursion in Haskell because it is only evaluated when needed. I don't really want to get into it here since there are many resources online about it :) But this also isn't inherent to functional programming or pure function programming.
Re:Why Haskell is suited to IO by mattdeboard on Monday July 04, 2011 @01:48PM (#2727221)
Interesting, thanks for taking the time for in-depth explanations.
Re:Why Haskell is suited to IO by eru on Monday July 04, 2011 @05:23PM (#2727923)
Also you don't need to use recursion too much, when writing Haskell code. You should stick to using combinators over your (recursive) data-structures. Think fold, map, filter, and friends.

Alas, you still have to be able to understand recursion to get anywhere.

Re:Why Haskell is suited to IO by kemiller on Monday July 04, 2011 @01:17PM (#2727108)
"Pure" in this context is basically short for "purely functional." Most functional languages have exceptions -- notably for I/O. Achieving 100% functional behavior is, it turns out, really really hard, and that's what makes Haskell notable.
Re:Why Haskell is suited to IO by yummyfajitas on Monday July 04, 2011 @11:41AM (#2726804)
Pure means that functions have no side effects - a function is purely a mathematical object defined by it's return values.

For example, f(x) = 2*(x+1) is pure. f(3) == 8, and it is completely safe (in terms of yielding the proper return value) to replace f(3) with 8 anywhere in your program.

Similarly, print world "foo" is referentially transparent - print world_in_which_foo_wasnt_printed "foo" == world_in_which_foo_was_printed. It's completely safe to make the substitution (restOfProgram (print world_in_which_foo_wasnt_printed "foo")) -> (restOfProgram world_in_which_foo_was_printed).

Referential transparency makes it easy to reason about programs. A function of type Int -> Int will never touch a variable of type OutsideWorld, and can always be replaced by it's output.

For those wondering what this has to do with monads, it's fairly simple. A pure program without monads requires a lot of plumbing concerning the world variable:

    f: World, Int
        world, result <- action1 world 3
        world2, result <- action2 world
    ...
    return (worldN, result)
Monads are merely syntactic sugar to suppress the world variable.

[edit: fixed formatting.]

Re:Why Haskell is suited to IO by dons on Monday July 04, 2011 @11:46AM (#2726811)
Pure code is code with no side effects. The result of a pure function only depends on its input parameters, and not the state of the world. Such code is by-default thread-safe, composable and tends to be simpler to understand than code with multiple interactions with external state.

It also admits many optimizations in the compiler, garbage collector and runtime system that are not possible for code without such safety guarantees.

It is this IO and thread throughput and scaling results that are being hinted at in this post, I think. And projects like Snap and Yesod are taking advantage. http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-...