Live data from Hacker News

Mastering Time-to-Market with Haskell

fpcomplete.com

81–90 of 120 posts

Re: Mastering Time-to-Market with Haskell

#81
post #70

Earlier quoted context omitted.

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 everyth…

> 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).

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

#82
post #80

Earlier quoted context omitted.

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.

I.e. look at how PureScript does it [0]. Haskell could do the same. [0] https://pursuit.purescript.org/packages/purescript-arrays/3....

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

#83

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 expres…

> 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.

Re: Mastering Time-to-Market with Haskell

#84
post #48
post #32

Earlier quoted context omitted.

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 "unp…

> 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…

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

#85
post #79
post #66

Earlier quoted context omitted.

> Nobody knows if Haskell's design is great for software development We can certainly say that uncontrolled side-effects, manual memory-management and dynamic types is bad for software development in the large. I'll stop here because I don't which to argue the semantics of what does are does not constitute significant use or significant research.

> We can certainly say that uncontrolled side-effects We most certainly cannot say that. There's no indication or even a hint that uncontrolled side-effects are a cause of expensive bugs. As a Haskell developer, however, I assume that you consider mutation to be a side-effect (because in pure-FP mutation is a side effect), and it is true that uncontrolled, non-transactional global-state mutation is not such a great i…

> There's no indication or even a hint that uncontrolled side-effects are a cause of expensive bugs.

Uncontrolled side-effects destroy the ability to reason about software and when one can no longer reason effectively, bugs will happen. This is obvious to anyone who has worked on large systems. Whether it matters or not, depends on the domain. In finance, it is absolutely critical that we can reproduce a calculation and that for example, the current date is not read from the system deep inside the code somewhere. Having the compiler guarantee this for us is a huge win.

> Absolutely, and you can get automatic memory management for a fraction of the cost. > You get static types for a fraction of the cost, too.

What do you actually know about the cost of Haskell adoption? If you want to accuse me of making unsubstantiated claims, your position would be more tenable without making them yourself!

Re: Mastering Time-to-Market with Haskell

#86
post #32
post #30

Earlier quoted context omitted.

You mean non-purely functional languages.

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 "unp…

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

#87
post #22

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 expres…

> 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.

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

#88
post #80

Earlier quoted context omitted.

I.e. look at how PureScript does it [0]. Haskell could do the same. [0] https://pursuit.purescript.org/packages/purescript-arrays/3....

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.

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

#89
post #32

Earlier quoted context omitted.

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 "unp…

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…

> 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

#90
post #89

Earlier quoted context omitted.

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…

> 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…

Sure.
Post reply on HN