Hacker News new | ask | show | jobs
by daxfohl 3399 days ago
I'm just starting with Haskell and PureScript. So far I'm liking the latter better. It solves a few of their gripes with respect to strings, laziness and records, plus has a more granular/extendable effects system and cleans up the standard typeclass hierarchy. Also `head []` doesn't crash.

Of course Haskell is more mature, has support for multithreading and STM, compiles to native, so it's more performant. But PureScript integrates with JS libraries and seems "fast enough" in many cases. I think it's more interesting as a project too: the lack of runtime and laziness means the compiler code is orders of magnitude simpler than Haskell's, so I could see a larger community building around it if it catches on.

Given that they were on Python earlier, I wonder if PureScript would have been a better choice.

5 comments

I think PureScript should catch on. The runtime performance story is much more predictable than Haskell, it integrates trivially with the most valuable target platform: JS, it has small output, fixes the warts of Haskell and yet is still pure.

Aside from apps at work, I made some simple physics demos with it http://chrisdone.com/toys/ Perfomance seems good.

While I really like it, I think it needs a more familiar syntax (to mainstream devs) to be anything more than a niche thing. I'd like to see something in the middle kind of go the typescript route, where valid+pure JS is valid WhateverScript, and with generally JS-y syntax, but with PureScript's additional features and effects systems.

It may end up really ugly though: how would you define operators while preserving JS semantics (e.g. no currying)?

You use purescript at work? Are they internal-facing apps or external-facing? Would love some more details.
> Aside from apps at work

Now I'm curious :)

> It solves a few of their gripes with respect to strings, laziness and records, plus has a more granular/extendable effects system and cleans up the standard typeclass hierarchy. Also `head []` doesn't crash.

Check out ClassyPrelude[1]. It's a (n opinionated) alternate Prelude that wraps many things up into much more "modern" interfaces. `head` has been replaced with `headMay` (which, as you can figure, returns a `Maybe a`). Most functions can now handle `Text` fairly seamlessly. For an application developer, it's fantastic.

[1]: https://hackage.haskell.org/package/classy-prelude

I can't imagine using a haskell-like language without laziness. It's what makes it possible to actually write small reusable functions.

Tell me, have you ever used foldr in Purescript? It just doesn't lead to reusable logic there, so I have no idea why you would.

But in Haskell, foldr is used everywhere. Laziness means that logic built with it is actually reusable.

Here is foldl implemented using foldr in PureScript, along with an example of using laziness to gain modularity:

http://try.purescript.org/?gist=63d81adf9f5257ffa4f576df2658...

> I can't imagine using a haskell-like language without laziness. It's what makes it possible to actually write small reusable functions.

I don't understand your point. Why is laziness a requirement to write small reusable functions? Are you thinking about currying?

OCaml is (relatively) similar to Haskell and is not lazy. Function currying does not require laziness.

It's unrelated to currying.

It's also hard to explain, but if you're used to Haskell, working with an eager-by-default language such as OCaml or ML is mildly annoying. You can adapt, of course, but it does seem as if gluing stuff together is trickier with eager evaluation.

There are downsides to lazy-by-default, of course.

There's a classic paper that answers this well: "Why Functional Programming Matters."

(Not a quick read, but not too huge, and it is a classic that is well worth reading sometime).

Folds are used in purescript all the time! Sure a foldr is less useful because it doesn't have the nice lazy preserving properties, but you can have strict left folds, which are tail recursive, and thus run in constant space.

Elm, another haskell-like, _strict_ language, models entire applications around the strict left fold over events https://guide.elm-lang.org/architecture/

We actually do the same in Jobmachine. The application is driven by a strict left fold over incoming events and current state.

There's a reason I said foldr. In Haskell, even foldl is implemented with foldr. It's that powerful of a tool. In contrast, foldl is far weaker, and necessarily strict in its input. It loses nothing moving to mandatory strictness. But foldr loses everything.
The hard thing to swallow with purescript is whether row types are really worth the complexity they add.
I think it's a much easier pill to swallow than laziness.
I don't really use foldr even in Haskell. It's almost always a performance problem.
> I wonder if PureScript would have been a better choice.

I have an aversion (based for a large part on prejudice) of things that involve Javascript and its ecosystem :)

I hear many good things about Purescript’s effect system, but I haven’t studied it in detail. This is definitely one of the areas where there is room for improvement in Haskell.

Regarding the type class hierarchy and head being partial, those weren’t really an issue in practice.

You don't have to study its effect system in detail, there's not much to it. Instead of IO a you have Eff e a, where e is a record of effects, using PureScript's records support. The neat thing is that statements in the Eff monad tend to get compiled to x; y; z in the resulting JavaScript, which is great, you don't pay a performance penalty. Check out the source code in this demo: http://chrisdone.com/toys/elastic-collision-balls/ There is still some overhead for currying, but there's a lot of room for decurrying saturated calls.

You might be happy to hear there is a PureScript native compiler. I'm also averse to JS things, I use PS but don't use the node-based tools to build it.

That was informative, thanks!
A while ago I wanted a better JS for a project, so I tried PureScript and liked it, I have a little experience with Haskell and it was easy to understand and more consistent, however when I tried to do UI components I chose halogen and damn it was too complicated, ended going back to ES6 and React.
What was complicated about it? I'm just getting started with it and it seems pretty straightforward after two days. In fact, I'd say it's almost stupidly easy -- one state handler, one change monitor, and one renderer, done. None of the mangling local state/props/component/JSX/global state/flux/redux stuff in React. So many knobs and options and plugins, the React ecosystem strikes me as a zoo comparatively.