Today, on the #purescript channel of the functional programming Slack, I wrote "I think PureScript is the best choice for anyone building a server in 2020." To that, Peter Andersen asked:
Wow! What are the key things in your eyes that make it the best?
Now if that's not an invitation to blog, I don't know what is!
So, here are four reasons that PureScript is the best way to build a server in 2020. I'll tl;dr them here, but you should stick around for the bonus reason at the end as well!
- Hello world
- Portability
- Language
- Community
Hello world
The time it takes to get a server up and running in PureScript is as fast as a hello-world
server in JavaScript and Python. At Meeshkan, we regularly have to push out a server for some random part of the stack, and my fingers can get in the PureScript+Payload groove as fast as Node+Express or Python+Flask.
npm init -y
npm install purescript spago xhr2
init
spago install payload
spago build
Then mosy on over to src/Main.purs
and paste:
module Main where
import Prelude
import Effect (Effect)
import Effect.Aff (Aff)
import Payload.Server as Payload
import Payload.Spec (Spec(Spec), GET)
type Message
= { text :: String }
spec ::
Spec
{ hello ::
GET "/hello"
{ response :: Message
}
}
spec = Spec
hello :: {} -> Aff Message
hello _ = pure { text: "world" }
main :: Effect Unit
main = Payload.launch spec { hello }
Then, in bash:
spago run
Try curl http://localhost:3000/hello
, get back {"text": "world"}
.
The package Payload is one of several ways to build a server in Purescript - there's also Hyper. And there are libraries to work with GraphQL and OpenAPI as well.
In the "just get stuff done" department, PureScript rivals languages like JavaScript, Python and Go. The next time you need to crank out a server, remember that PureScript is imminently crankable!
Portability
PureScript is a front-end for multiple languages. It compiles to JavaScript, Go, Python, Erlang, Haskell, and C++, just to name a few. So the "write once, use everywhere" philosophy that made isomorphic Node+Browser development so popular is even more powerful in PureScript. Furthermore, because PureScript is just transpiling, it can be deployed to environments like Heroku, Vercel or GCP by putting spago run
in your package.json
for the run command.
If your server needs to access custom language features, like a ML model in Python or a killer library you can't live without in JavaScript, PureScript's foreign function interface allows for seamless interaction between PureScript and the target language. For example, if in PureScript we have:
-- Main.purs
module Main where
foreign import hello :: Int -> Effect String
Then you just need a Main.js
in the same folder:
// Main.js
exports.hello = (i) => () => `${i}`
And PureScript automatically links them up.
The day you need to migrate your server from language X to language Y, you'll be glad you wrote most of it in PureScript. I recently had this experience with WebAudio - I wrote a proof of concept in PS->JavaScript and did PS->Wasm once I was ready to make it more performant at the expense of debugability.
Language
PureScript is in the same category of languages as Haskell, Idris, Agda and Coq. Because these languages lend themselves well to proving things, really smart people tend to flock to them, which means the discussion is usually pretty heady and newbs can get easily lost.
However, this discussion masks the reality that functional languages are no more difficult to get started in than other ones. Imagine that you need to write a function that increments positive integers and returns some nullish value for anything less than 0. Compare an implementation in Python to the same in PureScript.
def posinc(i):
return None if i <= 0 else i + 1
posinc i = if i <= 0 then Just i else Nothing
I've shown these "Rosetta stone" examples before many-a-coder and have yet to find someone that feels one is inherently more difficult than the other.
If I were a betting person, I'd bet that the type safety and clean, readable code that come with the Haskell family of languages will save you many-a-bug in production and cause you to never work with anything else. But alas, I don't bet. The only point I'll make here is that you don't need to have ten years of software development under your belt to grok PureScript. Getting up and running is no different than learning Python.
...a quick aside to those of you who are into FP and swear up and down by it. PureScript is not as full featured as Haskell, and doesn't have out-of-the-box dependent types like Idris/Agda, but it has a minimalistic feature set that allows you to do most of the stuff you'd actually want to do in a real-world app. Plus, it is really easy to deploy on Heroku, Vercel or AWS Lambda.
Community
The PureScript community has an active, non-toxic Discourse and Slack populated by helpful people that answer each others' questions and share resources. Additionally, most libraries you'd ever need for a basic server have already been written with ample documentation on Pursuit, and novel ideas are being explored all the time.
A lot of PureScript coders also use dhall as an alternative to JSON for configuration. If you use spago
as I did above, you're using dhall
and you'll see dhall
files in your directory. For anyone that has ever been hit by a configuration bug, you know the importance of getting config right early on in a project. PureScript+Dhall is an unbeatable combo in this regard.
Bonus
I promised you a bonus, and here it is. While Meeshkan is an equal-opportunity tester, we have additional bells and whistles in our service that we use if you provide us with certain assets like an OpenAPI spec or GraphQL schema. We also have tools that use the types of certain languages to create even more powerful tests, and PureScript is on the list. So by going with PureScript, your service will be more testable by Meeshkan. As our stack becomes more mature, we regularly open-source PureScript libraries to help folks build better servers and write more powerful tests.
Conclusion
PureScript is still in early-adopter mode, and the community is tiny. I personally was reluctant to try it out at first because I didn't see the point over using Haskell. However, the velocity of development/deployment, the limited feature set one can wrap one's head around, and the portability won me over. The next time you're building a server, or even in your current server if it is in a language to which PureScript compiles, give PureScript a shot!
Top comments (2)
Great article, I really enjoyed it! Do you have any experience in using Purescript for frontend development, or are you mainly using it as a backend tool?
I'm interested in comparisons with Elm, if you have tried it that is :)
Hi!
I wrote klank.dev in PureScript using Halogen. Elm has a more mature ecosystem of frontend components and a larger user base, whereas PureScript/Halogen is less opinionated, less full-featured & a bit more klunky in the type system but (IMO) more powerful. For klank, it was a natural fit as the backend is also in PureScript, so I'm able to share types across the monorepo. I'd recommend reading through the Halogen guide in the repo: it covers the basics in six approachable lessons, and by the end you'll have a good sense of how it compares to Elm.
Thanks for reading!