News for hackers. Stuff that matters.
Re:Mastering Time-to-Market with Haskell by millstone on Tuesday November 22, 2016 @02:53AM (#13012426)
IME Haskell development has a sort of bell-curve to it. Initially, you're spending a lot of time prototyping, fumbling around trying to find the right abstractions. Here Haskell mostly gets in the way: you have to declare up-front which functions do I/O, etc.

But once the core abstractions are settled, you start to reap its power. The type system catches tons of potential errors. Combinators allow for enormous expressiveness. Here you're rolling: Haskell is in its zone!

But then you hit a wall. Laziness makes for brutal debugging. Singly linked lists actually suck. Performance optimization is a black art. You find yourself longing for a language with simple semantics and mechanical sympathy. Now Haskell is bumping up against the real world.

Haskell has its sweet spot somewhere between "bang this out by 5pm" and "ship this to a million users". (No surprise it's popular in academia.)

Re:Mastering Time-to-Market with Haskell by pka on Tuesday November 22, 2016 @06:26AM (#13013304)
> Initially, you're spending a lot of time prototyping, fumbling around trying to find the right abstractions. Here Haskell mostly gets in the way

The opposite is true: here Haskell helps to find the right data structures/abstractions incredibly fast. The ability to quickly construct and reconstruct a high-level skeleton of your program without actually having to implement anything makes prototyping much easier and faster than in comparable dynamic languages.

> But then you hit a wall. Laziness makes for brutal debugging.

Laziness can sometimes surprise you in bad ways, but it's not like it's impossible to debug.

> Singly linked lists actually suck.

Just replace them with the right data structure then? Even for big codebases and fundamental program abstractions that's a 15min job, because of types.

> Performance optimization is a black art.

I agree. But then again - you don't have to write everything in Haskell. Writing the critical 1% in C, testing the shit out of it and calling it from Haskell is absolutely fine.

Re:Mastering Time-to-Market with Haskell by jstimpfle on Tuesday November 22, 2016 @08:59AM (#13014130)
Why, in your opinion, is it faster to construct a "high-level skeleton" than in dynamic languages?

> Laziness can sometimes surprise you in bad ways, but it's not like it's impossible to debug.

The last message I get was something like "Array.Array: Index out of bounds". Program crashed. No idea where the error originated. The answer I got was "yeah, in GHC 8 there will be some support for stack traces".

Re:Mastering Time-to-Market with Haskell by pka on Tuesday November 22, 2016 @09:11AM (#13014206)
Because of types, basically. You can construct the core data structures of your program and the types of the functions operating on those data structures without having to actually implement said functions. When the types fit together, i.e. your program is logically consistent, you can start filling in the actual code.

This is much faster than writing a large chunk of code, playing around in the REPL thinking everything is ok, only to realize one week later that you didn't think through some core aspect of your design and then having to refactor a sizeable piece of your codebase.

> The last message I get was something like "Array.Array: Index out of bounds". Program crashed. No idea where the error originated.

It is an unfortunate historical artefact that there are still partial functions (i.e. functions that may crash) in the Haskell base libraries. It is generally advised to avoid such functions, but this is not very clearly communicated to newcomers to Haskell.

For example, Elm, a language largely inspired by Haskell, doesn't have partial functions. This is why it prides itself in "not having any runtime errors in production" (excluding things like compiler bugs or unsafe JavaScript libraries, of course).

Re:Mastering Time-to-Market with Haskell by jstimpfle on Tuesday November 22, 2016 @09:43AM (#13014413)
The error was my own. Only I couldn't figure out where exactly.

Such errors can't be avoided. I need arrays for performance.

If performance is no concern I can use Maps, but I still need indexing ("partial functions") for architectural reasons: separation of concerns - can't make "safe" graphs where everything holds a reference to everything "related".

I just don't buy the idea that partial functions can be avoided.

Re:Mastering Time-to-Market with Haskell by pka on Tuesday November 22, 2016 @10:31AM (#13014742)
I.e. look at how PureScript does it [0]. Haskell could do the same.

[0] https://pursuit.purescript.org/packages/purescript-arrays/3....

Re:Mastering Time-to-Market with Haskell by jstimpfle on Tuesday November 22, 2016 @11:09AM (#13015013)
Sure, I can use a Maybe variant, but the consequence would be that I wrap the whole program in a layer of maybes for cases that I "know" shouldn't happen but happened -- because I do make mistakes.

Or in other words, an "AssertionMonad". No thanks, I'm perfectly fine with assertion errors (i.e. "Index out of bounds"). I just need help with finding my own errors. Stacktraces are a good thing.

Re:Mastering Time-to-Market with Haskell by pka on Tuesday November 22, 2016 @11:34AM (#13015224)
I agree, stack traces are a good thing.

For the time being, make a helper function:

ixWithString :: String -> Int -> Array a -> a

check the bounds inside and error out with a custom message when the index is outside the array bounds.

Re:Mastering Time-to-Market with Haskell by natec425 on Tuesday November 22, 2016 @09:52AM (#13014484)
> For example, Elm, a language largely inspired by Haskell, doesn't have partial functions.

I may be wrong, but I don't think this is technically true. I don't think Elm has only total functions, but it does avoid a lot of common, error-prone partial functions (e.g. accessing elements from a collection).

Re:Mastering Time-to-Market with Haskell by pka on Tuesday November 22, 2016 @10:34AM (#13014760)
I am not following Elm closely and may be wrong, but I'd be surprised. The creator (Evan) is really picky about having unsafe features in the language.

It's even impossible to upload a package to the official repository containing JavaScript code without prior approval, because the native code may crash!

Re:Mastering Time-to-Market with Haskell by Ixiaus on Tuesday November 22, 2016 @10:05AM (#13014570)
It is faster for large programs. For small programs, I think Python is great but you also have to consider that there is no such thing as prototype code and a small script (usually but not always) balloons into something more involved than was originally intended.

THAT is where Haskell shines, the ability to refactor and expand fearlessly and aggressively.

I think for large or complex programs Haskell is much faster for constructing a skeleton because it's usually not the logical operations that trip us programmers up, it's the data flow and correct alignment of types, which are implicit in a dynamically typed language and explicit in Haskell.

So, it's kinda-sorta like writing your ideas down in a structured language which enables you to "see" the abstractions in a rigorous light, then the ability to refactor aggressively and safely kicks in so once you can see your abstractions you can quickly adapt for better ones.

So I think the initial work is made quicker in that it forces you to excogitate then because it's in some concrete form you can see it clearly and take advantage of quick turnaround time in refactoring.

Re:Mastering Time-to-Market with Haskell by vog on Tuesday November 22, 2016 @03:59AM (#13012720)
> But then you hit a wall. Laziness makes for brutal debugging. Singly linked lists actually suck. Performance optimization is a black art

To be fair, these issue are more-or-less solved by newer functional languages, such as OCaml or Rust.

Re:Mastering Time-to-Market with Haskell by nilkn on Tuesday November 22, 2016 @11:28AM (#13015172)
Practically speaking, OCaml is not exactly just a drop-in replacement for Haskell. For instance, Haskell has world-class support for STM which makes it arguably one of the best languages out there for single-machine multicore concurrency.

Also, OCaml is still two decades old. I find it very bizarre that you attempted to group it in with Rust as a "new" language.

Re:Mastering Time-to-Market with Haskell by srean on Tuesday November 22, 2016 @06:45AM (#13013380)
Technically you are correct (the best kind of correct) but from where we sit today in time, Haskell and OCaml appear as are peers. They probably have some 4~5 years between them, and probably less if you consider ML.
Re:Mastering Time-to-Market with Haskell by amelius on Tuesday November 22, 2016 @04:48AM (#13012930)
You mean non-purely functional languages.
Re:Mastering Time-to-Market with Haskell by vog on Tuesday November 22, 2016 @05:01AM (#13012991)
I assume you mean strict (the opposite of lazy) instead of non-pure (which means imperative).

Well, even then, Rust does not only give you control over execution order, but also tight control over memory management, while keeping it safe.

Haskell allows for good reasoning about correctness. In OCaml, you can additionally reason about execution order, but memory management and garbage collector are still somewhat "unpredictable" (i.e. hard to reason about). On top of that, in Rust, you can reason clearly about memory usage and aliasing.

These new, modern languages follow a clear path about keeping quality and correctness (hence safety) while having more and more control over performance, without going back to low-level where you would loose clarity about correctness and safety.

(Note, however, that the distinction between correctness and performance is over-simplified here, because performance can also be part of correctness, e.g. for real-time systems, or in systems where scalability is an important requirement.)

Re:Mastering Time-to-Market with Haskell by pron on Tuesday November 22, 2016 @06:20AM (#13013276)
> pure (the opposite of imperative).

Pure is not quite the opposite of imperative; declarative is the opposite of imperative, although in practice it is true that pure functional languages tend to be more declarative that imperative functional ones.

You can have pure (AKA referentially transparent) imperative languages if they are synchronous[1]. The synchronous style is especially well suited to reactive/interactive applications, and quite popular in hard realtime applications.

Also, we don't really have exact definitions to any of these terms (imperative, pure, functional, declarative). Here is my attempt for approximate, problematic definitions:

* Functional -- a language that models most/all computations as (possibly partial) mathematical functions, and constructs a program by assembling those functions.

* Imperative -- a language that models computation as state transitions, specifying what state should the computation have at each step.

* Declarative -- a language that describes what result should the program give (as a function, a relation or a behavior) rather than at each step.

* Pure -- a language where the semantic value of the composition of syntactic terms can be determined by the semantic value of each of the component terms and no others.

[1]: https://en.wikipedia.org/wiki/Synchronous_programming_langua...

Re:Mastering Time-to-Market with Haskell by catnaroek on Tuesday November 22, 2016 @11:13AM (#13015060)
You've just defined “pure” as “can be given a denotational semantics”. I have news for you: even ALGOL can be given a denotational semantics.

---

@pron

Nowadays I prefer the terms “effect-free” and “effectful”, rather than “pure” and “impure”, since I don't want to suggest that effects are somehow “wrong” or “evil”. By definition, values are effect-free. An effect is anything that invalidates some equational law that holds for values.

For example, integer equality is decidable, and `x == x` evaluates to `true` when `x` is any integer value. However, if we substitute `x` with the expression `foo()`, where:

    int counter = 0; // or any other initial value
    int foo() { return counter++; }
Then `foo() == foo()` doesn't evaluate to `true` anymore. Hence `foo` is an effectful procedure.

Of course, nontermination is an effect too. If we had defined `foo` as:

    int foo() { while(true); return 0; }
Then `foo() == foo()` would similarly fail to evaluate to `true`.
Re:Mastering Time-to-Market with Haskell by pron on Tuesday November 22, 2016 @11:37AM (#13015254)
Yeah, I know my definitions are problematic. Remember that the term "referential transparency" was introduced to computer science by Strachey in his Fundamental Concepts in Programming Languages as a property of procedural, imperative languages. How would you define pure?

---

> An effect is anything that invalidates some equational law that holds for values.

Ah, I can certainly accept that as a definition, except that I'm not sure how different it is from mine, because the equational law you refer to applies to syntactic terms (`foo` in your example) and the language's equality operator (`==` in your example). It's easy to come with an equivalence relation that would hold for `foo`, but not at the syntax level (e.g., equality that takes `foo` to mean `foo`'s definition and the content of the heap, and the value of `foo` would not be its return value but its behavior -- i.e., the behavior of foo for equal heap contents is always the same).

Re:Mastering Time-to-Market with Haskell by catnaroek on Tuesday November 22, 2016 @02:19PM (#13016702)
> except that I'm not sure how different it is from mine, because the equational law you refer to applies to syntactic terms

An effectful language can be given a denotational semantics. At least from what I've seen, when most people say “pure”, they mean “effect-free”.

> It's easy to come with an equivalence relation that would hold for `foo`, but not at the syntax level [emphasis mine]

Yep, indeed, that's the whole point.

Re:Mastering Time-to-Market with Haskell by pron on Tuesday November 22, 2016 @02:43PM (#13016928)
> when most people say “pure”, they mean “effect-free”

But saying "effect free" doesn't mean much unless you define what an effect is, and what constitutes an effect depends on the language. I meant to define the same thing without referring to another vague definition.

Re:Mastering Time-to-Market with Haskell by catnaroek on Tuesday November 22, 2016 @02:46PM (#13016962)
I already defined above what an effect is. My definicion is technically precise and language-independent.
Re:Mastering Time-to-Market with Haskell by pron on Tuesday November 22, 2016 @03:14PM (#13017237)
OK, so you define effect-freedom using the language's equality operator. I agree it's a better definition than mine, but I think assembly language and BASIC would still qualify as effect-free (provided there's no concurrency) even though some people would not consider them pure.
Re:Mastering Time-to-Market with Haskell by catnaroek on Tuesday November 22, 2016 @03:39PM (#13017449)
> OK, so you define effect-freedom using the language's equality operator.

Not the runtime equality testing operator. Rather, the language's static notion of contextual equivalence.

It just happens to be the case that most high-level languages provide a built-in equality testing operator that works on primitive types, returning `true` iff its operands are contextually equivalent values.

> I think assembly language and BASIC would still qualify as effect-free

I don't even know what a good notion of contextual equivalence for any assembly language would be.

As for BASIC, I haven't used the old ones, so I can't comment on them. I've used Visual Basic, which most certainly has effectful procedures.

Re:Mastering Time-to-Market with Haskell by pron on Tuesday November 22, 2016 @03:47PM (#13017508)
> Not the runtime equality testing operator. Rather, the language's static notion of contextual equivalence.

How is that different from denotational semantics?

> The ones that can be effectful or effect-free are specific computations, not whole languages.

Well, we could define an effect-free language as one where all programs are effect-free. But anyway, what is the "static notion of contextual equivalence" in assembly (or BASIC), and how can you write an effectful program in such a language?

Re:Mastering Time-to-Market with Haskell by catnaroek on Tuesday November 22, 2016 @11:27AM (#13015167)
Reasoning about correctness in Standard ML is easier than in either Haskell or OCaml, since induction on strictly positive datatypes actually works as a reasoning principle. You don't need to manually assert silly preconditions such as “this list is finite” (Haskell) or “this list isn't cyclic” (OCaml).

On the other hand, neither Haskell nor the MLs tackle the problem of safely managing ephemeral resources. Rust does this, but it sacrifices the ability to conveniently share immutable data structures (Rc and Arc exist, but they aren't very convenient). The good news is that this doesn't have to be a dichotomy. You can have GC for in-memory data structures and deterministic destruction for everything else: https://news.ycombinator.com/item?id=12766781

Re:Mastering Time-to-Market with Haskell by vog on Tuesday November 22, 2016 @11:35AM (#13015229)
> The good news is that this doesn't have to be a dichotomy. You can have GC for in-memory data structures and deterministic destruction for everything else

That's very interesting. Please correct me if I'm wrong, but I think this is not the final solution, either, because you still have the GC running, which prevents strict proofs about performance e.g. for real-time systems. Here, the Rust approach has benefits as it enables you to get very far without a GC.

Re:Mastering Time-to-Market with Haskell by catnaroek on Tuesday November 22, 2016 @11:36AM (#13015240)
Sure.
Re:Mastering Time-to-Market with Haskell by bjz_ on Tuesday November 22, 2016 @04:59AM (#13012985)
Purity is orthogonal to laziness. Languages like Idris, Purescript, and Elm are pure but also eagerly evaluated.
Re:Mastering Time-to-Market with Haskell by hikarudo on Tuesday November 22, 2016 @06:04AM (#13013239)
Except that laziness requires purity.
Re:Mastering Time-to-Market with Haskell by fdej on Tuesday November 22, 2016 @06:52AM (#13013404)
Only if you insist on determinism :-)
Re:Mastering Time-to-Market with Haskell by Tehnix on Tuesday November 22, 2016 @03:56AM (#13012711)
>But once the core abstractions are settled, you start to reap its power

This is so true. Once you get the types settled for your project, then it becomes a breeze to quickly add things and refactor over and over again, because maybe the spec or idea changed.

I've recently experienced this in both a Haskell project (using the Yesod framework) and I'm currently working on an Elm project, where I very much feel this strength also.

I'll have to agree with you on the debugging though - it is somewhat of an art, and not one I've completely mastered yet, since I haven't had that much need for it for now (haven't done that many production haskell projects).

Re:Mastering Time-to-Market with Haskell by the_af on Tuesday November 22, 2016 @01:37PM (#13016304)
> IME Haskell development has a sort of bell-curve to it. Initially, you're spending a lot of time prototyping, fumbling around trying to find the right abstractions. Here Haskell mostly gets in the way: you have to declare up-front which functions do I/O, etc

There's some evidence Haskell is pretty good at rapid prototyping.

Are you familiar with this '94 paper on rapid prototyping [ http://www.cs.yale.edu/publications/techreports/tr1049.pdf ] by Paul Hudak (RIP), sponsored by the Office of Naval Research & ARPA? The paper is a report on an experimental comparison of programmming languages for prototyping, and it's pretty cool because they were asked to implement a portion of a (heavily simplified) AEGIS weapons system! Unfortunately the paper and experiment are dated and have a number of methodological shortcomings (results were self reported; the examining panel didn't look at running code; requirements were very vague and mostly determined by each team, which makes the comparison difficult), but the results are pretty interesting regardless:

- Of all the teams, only the two Haskell teams delivered working code (though the examiners didn't look at working programs). This must be stressed: no other team delivered running code at all, much less on time!

- One of the Haskell prototypes delivered more features than the initial requirements asked for.

- The programmer of one of the Haskell teams had NO experience with Haskell before the experiment.

- Both Haskell prototypes were also the shortest in line count. Way shorter than the C++ prototype, which wasn't even finished or working in time!

I'd like to see the same experiment repeated under more rigorous conditions and with more modern languages, but the results certainly hint at Haskell being more than adequate at prototyping.

Re:Mastering Time-to-Market with Haskell by saosebastiao on Tuesday November 22, 2016 @02:44PM (#13016932)
1994 was well before the IO monad became the standard IO paradigm for Haskell, and a year before there was even a proposal on the table for monadic IO for Haskell. It makes me wonder what the language was like back then and whether the results would be repeatable with today's language.
Re:Mastering Time-to-Market with Haskell by the_af on Tuesday November 22, 2016 @03:55PM (#13017570)
Sure! I think Haskell would fare pretty well today, because the essential aspects haven't changed. It's still very suitable for prototyping and exploratory programming.

Of course, today it would have to go toe to toe against modern dynamic languages. In this case it'd be essential to demonstrate running code, which is arguably a huge advantage of static typing over dynamic typing; if you're only comparing source code, dynamic languages can get away with being terse and claiming "trust me, it works".

I imagine Haskell would still leave modern C++ coughing dust at the start line :)

Re:Mastering Time-to-Market with Haskell by sc4th1s on Tuesday November 22, 2016 @12:03PM (#13015471)
There's a reason Real World Ocaml has a section dedicated to the run-time system and no book on Haskell will ever go near it.
Re:Mastering Time-to-Market with Haskell by catnaroek on Tuesday November 22, 2016 @11:12AM (#13015043)
> You find yourself longing for a language with simple semantics and mechanical sympathy.

“Simple semantics” as measured how? The only good metric I can think of is the size of a formal specification.