12 ms·
PureScript: a statically typed language which compiles to JavaScript
- derengel 12y agoFrom the project docs: "Generate simple readable Javascript" - isn't this more of a disadvantage than an advantage? the created Javascript code won't be high performance, which matters a lot in mobile today.
- paf31 12y ago"Simple readable JavaScript" as opposed to the sort of output you might expect from compilers for other Haskell-like languages which attempt to preserve Haskell's semantics. Certainly there are cases where using techniques from pure functional programming can lead to poor performance (monadic recursion jumps to mind), but it is perfectly possible to write fast code using PureScript. And if you really need to squeeze out every last bit of performance, you can always write code in JavaScript and use the FFI.
- geoffc 12y agoI can vouch for the real world performance. Phil has used Purescript to dramatically improve the performance of our medical image viewer. It's pretty impressive stuff.
- eru 12y agoWhat's monadic recursion?
- paf31 12y agoConsider a recursive function like factorial: fact :: Number -> Number fact 0 = 1 fact n = n * fact (n - 1) This will build stack frames and fail with a stack overflow for large inputs. We can fix this by using tail recursion and an accumulator: fact :: Number -> Number fact = go 1 where go acc 0 = acc go acc n = go (acc * n) (n - 1) The PureScript compiler will recognize that every recursive call is in tail position, and will convert the function to a while loop. If we want to perform side-effects during the recursion, we typically use a monad to track the type of side effect in use. For example, we can use PureScript's Eff monad to trace information to the console: fact :: Number -> Eff (trace :: Trace) Number fact = go 1 where go acc 0 = do trace "Done!" return acc go acc n = do trace "Keep going ..." go (acc * n) (n - 1) In the case of the Eff monad, the PureScript compiler employs some special tricks in the optimizer to enable the tail call optimization, so we're still OK. But this is only possible because Eff is defined in the standard library (at least until we implement custom rewrite rules). In the general case, the compiler only sees applications to the monadic bind function of the underlying monad. For example, if we use the Writer monad instead: fact :: Number -> Writer String Number fact = go 1 where go acc 0 = do tell "Done!" return acc go acc n = do tell "Keep going ..." go (acc * n) (n - 1) which is equivalent after desugaring to the following code: fact :: Number -> Writer String Number fact = go 1 where go acc 0 = tell "Done!" >>= \_ -> return acc go acc n = tell "Keep going ..." >>= \_ -> go (acc * n) (n - 1) This is an example of "monadic recursion" - a recursive function whose return type uses some monad. In this case, the recursive calls are no longer in tail position, so the compiler cannot apply the tail call optimization. The result is that the compiled JavaScript might blow the stack for large inputs. The point is that idiomatic Haskell code is often not appropriate in JavaScript because of the different semantics, so it might not be appropriate in PureScript either. The good news is that many Haskell idioms have corresponding PureScript idioms (often using the Eff monad).
- eru 12y agoThanks! Another trick I've seen used is `naked' avoiding recursion in your code, and relying on combinators implemented in some optimized lower level code. Would that work with PureScript?
- paf31 12y agoYes - in fact, that's the approach we encourage for working with immutable arrays: https://github.com/purescript/purescript-arrays https://github.com/purescript/purescript-arrays
- codygman 12y agoI wanted to play around with this, maybe you do too... Install purescript: https://leanpub.com/purescript/read#leanpub-auto-installing-purescript https://leanpub.com/purescript/read#leanpub-auto-installing-... The code, put it in a file named recur.purs (or w/e you want): -- recur.purs module where import Control.Monad.Eff import Debug.Trace -- naive factorial function fact :: Number -> Number fact 0 = 1 fact n = n * fact (n - 1) -- factorial function exploiting tail call optimization by putting function in tail position (at the end) fact' :: Number -> Number fact' = go 1 where go acc 0 = acc go acc n = go (acc * n) (n - 1) -- use Eff monad to trace information to the console fact'' :: Number -> Eff ( trace :: Trace) Number fact'' = go 1 where go acc 0 = do trace $ "The answer is: " ++ show acc return acc go acc n = do trace $ "(" ++ show acc ++ " * " ++ show n ++ ")" ++ "(" ++ show n ++ " - 1)" go (acc * n) (n - 1) main = fact'' 8 Then to compile it: psc recur.purs --output dist/Main.js --main Recur Hope this is as educational (and fun) for others as it was for me.
- BinaryIdiot 12y agoYour minification process should be separate from your build process that's required to run it. This can generate JavaScript that's not a huge pain in the ass to debug, then you as the developer can minify it with existing libraries. Though I'm not necessarily sure it wouldn't be high performance just maybe a hair slower to load. Then again I don't know how well their generator works.
- paf31 12y agoPureScript developer here. Happy to see this here, and happy to answer any questions.
- mhd 12y agoWith some languages, a big part of the selling point is that it's the same or similar to a language the programmer already uses. Clojure and ClojureScript come to mind, or even server-side JavaScript. Now, with ClojureScript, another common selling point is the synergy with react -- something that would appeal even to people not using Clojure (maybe because they're averse to the JVM). So where is PureScript positioned related to this? Let's say I'm writing a backend in Ruby or Python and not Haskell, why PureScript instead of CoffeScript or sweet.js? (I'm actually interested in this, not intended as a put-down.)
- paf31 12y agoI think it's definitely possible to put knowledge of Haskell to use in PureScript, but it's not like Fay, Haste, GHCJS etc. where you can copy code verbatim. I think of PureScript as "an environment in which to write principled JavaScript". That requires that, to a certain extent, you should have JavaScript's semantics in the back of your mind while developing. For that price, you get ease of debugging and some tools which you don't have in many other compile-to-JS languages (an expressive type system, type classes, ability to refactor with confidence etc.) Of course, one of the best things about AltJS is the interoperability with other languages. PureScript won't be the best tool for every case, but it has a simple FFI. It's possible to write complete front-ends in PureScript, but I'd love to see more examples where PureScript is used alongside something else (I've used TypeScript with PureScript successfully, for example).
- mariusmg 12y agoCare for a little comparation with TypeScript ? If i know TS why should i look at PS ?
- paf31 12y ago(Copied from below) I've written quite a lot of TypeScript, and I generally feel very productive in it, but occasionally I feel like I want more from the type system (type classes, rank-N types, sum types, etc.) and tidier syntax. You might be interested in Bodil Stokke's recent Strange Loop talk, where she discusses why she switched from TypeScript. https://www.youtube.com/watch?v=yIlDBPiMb0o https://www.youtube.com/watch?v=yIlDBPiMb0o
- rtfeldman 12y agoIt's been picking up a lot of steam lately! Bodil gave a great talk on it at Strange Loop last week: http://www.youtube.com/watch?v=yIlDBPiMb0o http://www.youtube.com/watch?v=yIlDBPiMb0o
- tisue 12y agoSaw two great talks about PureScript at Strange Loop last week, one by the language designer, Phil Freeman, and another by Bodil Stokke. Both the language and — almost equally importantly! — the accompanying book seem really well done to me.
- agumonkey 12y agoIndeed, the book covers a large set of very interesting topics without ceremony.
- romaimperator 12y agoHere's a gem to use PureScript files with Rails and the asset pipeline. It let's you add and compile PureScript files similar to how CoffeeScript files are added. https://github.com/romaimperator/purescript-rails https://github.com/romaimperator/purescript-rails
- boothead 12y agoJust bought the book today ($10 is too low!). After a few nixos hiccups today, so far so good :-)
- giulianob 12y agoWhat's the advantage over something like TypeScript which is a superset of JavaScript but supports types as well?
- mck- 12y agoOr Dart for that matter?
- paf31 12y agoI've written quite a lot of TypeScript, and I generally feel very productive in it, but occasionally I feel like I want more from the type system (type classes, rank-N types, sum types, etc.) and tidier syntax. You might be interested in Bodil Stokke's recent Strange Loop talk, where she discusses why she switched from TypeScript. https://www.youtube.com/watch?v=yIlDBPiMb0o https://www.youtube.com/watch?v=yIlDBPiMb0o
- moomin 12y agoIf you want types like Java, TypeScript's probably a good choice. However, if you want the flexibility or the guarantees a powerful type system gives you, TypeScript's not going to cut it.
- chowells 12y agoThe advantage is that types aren't optional. People actually have to respect them.
- hawleyal 12y agoEw
- noelwelsh 12y agoTypescript vs Elm? Fight! (I.e. what are the relative strengths and weaknesses of these two "modern languages targeting JS" offerings?)
- gregwebs 12y agoI think you meant Purescript vs Elm. disclaimer: I have used neither. Elm has its own package manager, not sure if that is good or bad! The biggest difference is that Elm is almost incidentally a similar strongly typed functional programming language and its biggest focus has always been on FRP (functional reactive programming) to simplify UI programming in the browser.
- noelwelsh 12y agoYes, I meant Purescript.
- sassyalex 12y agoGreat language, but javascript code is clean, why not only keeping javascript style and adding typechecking and es6 by default..
- andrewchambers 12y agoJavascript being clean is your own (possibly misinformed) opinion.
- pmontra 12y agoI agree that's a matter of opinions but I think that the OP has a point. JavaScript is easy to understand for everybody coming from C, Java or PHP even if its core is very different from those two languages. Haskell might be cleaner but it's difficult to get for people that used only procedural languages, which are most of the programmers working today (especially if the expected domain for PureScript is web programming, frontend or backend). There is a functional language called Elixir which runs on the Erlang virtual machine. Elixir has been designed to look like Ruby even if it's very different. That makes Ruby programmers (and maybe Python ones too) feel at ease in their first approaches with the language. When you realize how different the two languages really are you already grokked enough of Elixir to keep you going. There isn't that feeling of "oh my, I can't make it" one might have when looking at code like this http://svn.openfoundry.org/pugs/src/Pugs/Eval.hs http://svn.openfoundry.org/pugs/src/Pugs/Eval.hs when knowing only about C/Java/PHP/Python/Ruby Anybody knowing Ruby or possibly Python should compare that with this https://github.com/elixir-lang/plug/blob/master/lib/plug/conn.ex https://github.com/elixir-lang/plug/blob/master/lib/plug/con... So, my take is that if a language designer wants to create a functional language that will lure really many procedural programmers into it, s/he has to design something that looks like C or Java. PureScript is too much like Haskell (plus I hate indentation-sensitiveness, but that's almost only a subjective matter). Time will tell.
- Sirenos 12y agoEasy to understand != clean Javascript has enough implicit behavior and then some to make working with it a nightmare unless you remain extremely diligent with your coding practices. To a large extent, it's been around long enough for this to not be a major problem anymore, but is this an acceptable state of affairs for a language that dominates web programming? I'd expect most people to say "no".
- cmdrfred 12y agoI'm new to this but can someone enlighten me about what is the advantage of using this over pure JS?
- gamegoblin 12y agoType correctness can help eliminate an entire class of bugs (type mismatch bugs) found in dynamically typed languages, or various gotchas with implicit typecasting.
- cmdrfred 12y agoThank you. I know Python, JS, and PHP so type correctness is kinda foreign to me.
- toadkicker 12y agoThis is where I find programmers who are comfortable with static languages struggle with dynamic languages. There is a lack of understanding and this is yet another language trying to fix something that isn't fundamentally broken.
- paf31 12y agoI think it really depends what you're trying to do. There's definitely a class of problems where the impact of a runtime type error would be low. But there are plenty of other cases where you want to constrain what you or your users can do at compile time.
- zak_mc_kracken 12y agoFor those of you who want to see some code: https://leanpub.com/purescript/read https://leanpub.com/purescript/read
- lemming 12y agoOne thing I couldn't see anywhere - is PureScript strict rather than lazy?
- paf31 12y agoIt uses JavaScript's evaluation model - i.e. strict, but you can write lazy code using libraries, such as purescript-lazy.
- lemming 12y agoInteresting, thanks - I've been interested in a language like the Haskell.Next that SPJ described: strict evaluation but with effects controlled by monads. I'll give it a look!
- billpg 12y agoI find JS a thoroughly unpleasant language to work with. When will we reach the point where JS could be abstracted away entirely? (Just like how I never need to interact with assembly language any more.)
- rattray 12y agoIn what ways does CoffeeScript not suit you perfectly?
- marrs 12y agoNot speaking for the parent, CoffeeScript is even worse than Javascript. The killer for me is indentation forming scope. If you accidentally indent your code incorrectly, like when you're copy/pasting from one file to another, you can change the scope of all of the variables within. The other major problem I have with it is that it encourages us to go back to the class-based patterns that we've been trying to get away from.
- klibertp 12y agoPlease. Coffee has its problems, but being white-space sensitive is not one of them. It's entirely a matter of personal preference, just like preferring {...} instead of begin...end or using '' instead of "" for strings; it's not even as significant as prefix vs. infix syntax, which does have some practical consequences. You get indentation based blocks in quite a lot of languages, Haskell, F#, Python, Nimrod, MoonScript and others and it works there, I see no reason (knowing them all) for it to be a problem in Coffee particular case (to be honest, Coffee allowing inconsistent indentation in a single file is a bad design decision, though).
- rattray 12y agoYou aren't likely to see this again, but in case it helps, the following setting in Sublime Text's key bindings may help you: ``` { "keys": ["super+v"], "command": "paste_and_indent" }, { "keys": ["super+shift+v"], "command": "paste" }, ``` Though you should always be careful when copy/pasting code. I'm not sure how it encourages classes, I personally didn't even use classes at all for the first long period of my CoffeeScript life. And now only do sparingly.
- pjmlp 12y agoLooks nice, but my employer will never use anything other than JavaScript as browser language, unless a customer asks to do so.
- lmm 12y agoGet a better employer. I can understand thinking that e.g. existing options are not mature enough, but "never" is a stupid policy.
- pjmlp 12y agoQuoting myself > unless a customer asks to do so. which I agree with. Since 1986 I already have seen too much technology come and go, to be convinced to use "language of the month" at work.
- BinaryIdiot 12y agoSeeing these types of experiments are always interesting but just like CoffeeScript it requires learning two languages instead of one [so you an debug] which makes it a hard sale. Why not just write clean JavaScript? I know many want to make JavaScript the assembly language of the web but JavaScript is so much more complex than assembly I'm not sure that's necessarily a good goal to have. Granted I would love for more languages to be usable on the web; even if I thought JavaScript was the best language it's always good to have competition and alternatives. But I think that has to come through browser support. I wonder how feasible it would be to generate some sort of byte code similar to how Java and others work with the JVM.
- Tloewald 12y agoI wish a fraction of the effort going into "fixing" javascript went into fixing the real abomination: the DOM API (and CSS). Then everyone would benefit, even people using Dart, Coffeescript, and TypeScript.
- chadillac 12y agoI wish people would just realize that JavaScript isn't going anywhere and make the effort to understand it instead of trying to gloss over the quirks of it. Understanding the key parts of writing JS (closures, scope, GC, etc.) isn't all that hard and it seems like more efforts are geared towards an abstraction layer and/or framework than just learning the language in the first place. I think it's syntax and familiar looking and feeling environment cheerfully misleads people into thinking they are in a comfort zone, while they thrash around throwing sand in their own eyes, albeit with a familiar looking bucket and shovel.