How to learn PureScript in 2020?

I’m trying to learn PureScript. I have some experience in front-end development. I read 1 to 7 chapter on book[dot]purescript[dot]org but still don’t understand the type. I want to find tutorials like reactjs[dot]org/docs/getting-started[dot]html had. Build a simple web application step by step.

I found github[dot]com/JordanMartinez/purescript-cookbook but it’s lack of explanation.
I found thomashoneyman[dot]com/guides/real-world-halogen/ but I’m definitely not an intermediate PureScript developer.
And here are several tutorials out of date.

Currently I’m trying to do experiment with purescript-cookbook and hope I can understand those type things. I’m nervous, I feel it’s difficult to learn PureScript and start to make things and get a job. What should I do?


Have you gone through my learning repo?


+1 to Jordan’s Reference.

Also come join the Functional Programming Slack.
Invite here:
And then the Slack channels #purescript-beginners and #purescript.

My experience has been that people are happy to help out, provide guidance, and answer questions, no matter how basic :slight_smile:

Also, a good way to build up to RealWorldHalogen (…if Halogen as a framework is in fact your interest) is to work through the official Halogen guide first:

I got a lot of value out of the official guide.

Thanks for sharing your feedback. This helps us identify what needs improvement.

I agree with you about the difficulty (this was the hardest language for me to learn), so don’t feel bad if things are really confusing right now. I believe this is due to a few factors:

  • Functional programming style is very different than other languages
  • Lots of unfamiliar syntax
  • Lack of learning materials and tutorials

It’s a bit easier if you already have a background in Haskell or Elm, but we should definitely try to make the language accessible for folks who may only have some front-end JS experience.

Would you find it helpful if we had an equivalent react tutorial that walks through writing that tic-tac-toe game in PureScript? There’s an existing proposal to do that for our Halogen and React frameworks.

Make sure you’re also working through the exercises in each chapter. It’s really difficult to learn the material by only reading the text. If any of the exercises are confusing, please let us know. Unfortunately, I feel like that book goes a bit too deep into some of the trickier topics too early, and discourages readers who just want to start building a web app as soon as possible. I believe there are ways to improve the delivery where we emphasize building web apps, and hold-off on some of the more confusing content until later.

Also, note that the end of chapter 8 walks through building a web-app, so you’re almost there!


The wikipedia article on type theory explains what a type is. Well, at least it does it for an one definition of a type. I think this is related to Church vs. Curry. Intrinsic vs. extrinsic.

So why types then? I think even in programming the reason that you can use types to block paradoxes in formal logic is why you should use them. It just appears in multiple ways and in different contexts. Even if you deal with non-terminating/recursive programs, in some cases it guarantees there are few ways to constraint the program.

I’ve thought about writing a book on this, before I realized that it’d be worthwhile to just publish the whole thing in my blog. I think I’ll eventually change the links because I’ve decided to put a sitemap into the blog rather than write a book.

If you think that some of this could be included in the purescript book with some improvements, let me know what kind of modifications it’d need.


I don’t think the formal logic perspective is very likely to be helpful to beginners unless they already have a background in formal logic, unfortunately. I don’t think these are the kinds of resources we’re looking for in this particular case.


Haven’t gone through it, I thought it named “reference” so I was mainly reading :sweat_smile:

Thanks :grinning: I’m not familiar with slack, and the channel #purescript looks not very active, so I decided to ask this question here. I think forum is a better place for discussion, it’s easier to be seen by others who have same questions.

As for Halogen, it’s too difficult for me at present, maybe I’ll try it after go through Jordan’s reference.


Would you find it helpful if we had an equivalent react tutorial that walks through writing that tic-tac-toe game in PureScript?

That would be really helpful. :+1:

Make sure you’re also working through the exercises in each chapter. It’s really difficult to learn the material by only reading the text.

I did the exercises at first but soon give up. In Chapter 3 I don’t understand the Maybe type, and the book shows “You can do this” “And you can do that” “Actually chose one suit you” so I don’t know what should I put in my Main.purs file. Too many keywords and symbols I’ve never seen popped up like rabbits, so I decided to just keep going and try to grab any information I can understand, then exhausted at Chapter 7…



Thanks, I’ll try to digest those materials in this week :grinning:


Beginners surely will feel more comfortable with an example like to do app , tic-tac-toe etc. :rofl:

I brought this up because @Ding asked about what a type is. I’m not sure if the material answers that too well either. The objective of the book would have been:

  1. Provide knowledge to solving problems with programming.
  2. Help reader associate correctness and easy verifiability of a program to readability.
  3. Thin down the gap between theory and practice of programming.

And I tried to write it in a style that it would suffice that a person has basic education about mathematics.

Also I’m just saying, if you find a thing that would be useful to include in purescript book and it would help the audience of that book, I let you have it. This doesn’t mandate you to pick anything. Also I will eventually publish this stuff anyway, but it’ll be in my blog.

@Ding How about a mathematical model of a to-do-app or tic-tac-toe? :pig_nose: :rofl: Anyway, If you find something helpful there, we would be pleased to hear what it was. Also if you get discouraged by the material, don’t worry. If you’re really in hurry, it’d be enough to say that a type is a construct that describes how something can be constructed and deconstructed.

For example, with the aforementioned Maybe a. We got ways to construct it:

Nothing :: forall a. Maybe a
Just :: forall a. a -> Maybe a

And ways to deconstruct it:

maybe :: forall a b. b -> (a -> b) -> Maybe a -> b

And that’s it. Then you got operations that do things with these, for example map f where f is (a → b), you can transform the Maybe a to Maybe b. The signature of map is like this though:

map :: forall a b g. Functor g => (a -> b) -> g a -> g b

It’s an abstract signature and when it’s used in this context, the g is replaced by Maybe. The map can be used with multiple constructs that behave in the same way.

Update: :joy: I actually have tic-tac-toe in prolog, and a slightly bad? and maybe jargon-filled post about it, from 2019 february. (This is just something I thought was nice to show. Can be fun to look at but not important to understand for now, unless you’re really interested about this sort of interpretation of types as dialogue between computer and its environment.)

@cheery, If I was starting out with the language, I’d feel more confused after reading your explanation.

I think beginners need concrete examples. Elm does a really great job with these introductory materials. Here’s Elm’s coverage of Maybe:

Here’s what we have, which isn’t nearly as accessible:

Should we strive to match Elm’s thoroughness? This will be difficult for PureScript because it’s a bigger language with a lot more stuff to document.

@Ding, You may have a less frustrating learning experience if you start out with Elm to master the basics of functional programming, and then transition to PureScript once you’re ready for more language features. Pretty much everything you’ll learn in Elm applies directly to PureScript, and the syntax is really similar.

I’m curious, how did you discover PureScript and what led you to selecting it over the many other alt-JS languages?


Could you clarify what went through your mind when you saw that link, whether via the Book’s reference to it or the Documentation repo’s reference to it?

I’m wondering if the title of the repo itself is misleading.

Why did you think it’s not very active? It’s actually pretty active, and there’s a high chance you will get an answer. (Speaking from experience here.)

It’s fine if you don’t like Slack; however, I don’t want you not using it only because it seemed not very active because really, it’s the opposite.


I was using the standard of an active instant messaging group to match slack channel :grimacing:

The title of the repo make me thought it was something belongs to advanced learners, if someone need to figure out something under the hood they should try to read the “reference”.

When I saw the , the table of content looks overwhelming. Actually I feel it would be better to exchange the “table of content bold and not bold version” with the first section of “table of content detailed version”. Keep it simple at first glance.

Above are my personal experience feedback :grin:

Actually I was started with Elm… I was amazed by their useful error information and “undefined is not a function will never happen”. Then I feel like it’s a little bit too restricted, and then I read this looooong article , PureScript was mentioned multiple times in the comments area. Many people saying that PureScript is a good choice but yet has comprehensive ecosystem. Thus I chose PureScript :smile:

Thanks for your detailed explanation but it’s too difficult for me :persevere: I’m still confused by many basic syntax. When I see a block of PureScript, the first question come to my mind is: how to distinguish which one is a type, which one is a variable? I don’t know. And it seems that type is using along with variable everywhere, in TypeScript usually I’ll use colon “:” to tell the former is usually a variable and the later is usually a type,

a: b
c: d

but in PureScript:

a b
c d

I’m… :sob:

I still have a lot to learn. nothing, just, forall, functor, thin arrow, fat arrow, double colon, the period… I still have a lot to learn.


Thanks for the feedback!

The overwhelming nature of the ToC is a bit of the reason why learning FP languages are hard. There’s just a LOT going on. I experienced too many times where not understanding some foundational concept bit me later when I was working with more complicated libraries. So, my repo tries to be as clear and concise as possible while still explaining all one should need to know.

The detailed ToC exist so one could easily jump to any part in the repo. I guess it’s my temporarily solution to the problem of navigation in that repo. I wasn’t sure how many levels deep the ToC should be. Too few and it’s just an overview without allowing you to skim it. Too many and its overwhelming.

Also, I can see why the name would be understood that way. In some ways, the name is fitting and in others it is not. It’s definitely not a “quick-start” guide to PureScript. It’s more like an “in-depth” beginner’s guide to PureScript, so one is less likely to be confused later.


@Ding Well, let’s start with basics then. The stuff you’ve told so far is really interesting. I believe you when you say that it’s difficult to you. Just don’t worry that you would not be smart enough, I think you are. You can see everybody agrees the documentation needs work, and you partially know a lot of this if you’ve learned Elm. If we discuss here about the difficult things, it can be used to improve the documentation and that helps the community to grow.

If we start from the basics, we got type declarations just like in the language you’re coming from. Elm uses a single colon on type declarations. Purescript uses double colon. I think the preferred custom would be use of the single colon because types are important. Though Purescript ended up retrieving this feature from Haskell that uses the single colon differently. Either way it’s ok I guess.

In purescript, you’d be writing:

a :: b
c :: d

Type, b and d in this example, could be thought of as terms that determine how other terms, a and c, should be interpreted.

The game semantic interpretation may be useful here. Types in Purescript can be interpreted as games. Type describes what kind of game you play, and the definition is a strategy that never loses that game.

Now I think this should be checked whether it’s correct. I think that the idea of “not losing” allows you to define strategies that repeat infinitely many times and do everything to stop the game from progressing. The traditional way to explain the interpretation is to say that the definition is a strategy that always wins the game. However it’d be a non-turing-complete language that we’d be describing if you had to always win instead of preventing that you ever lose.

  1. If we got something like (Unit), it’s a game where you always win. You don’t need to do anything and you can answer with the (unit). That is, unit is a valid play to Unit, and this may be claimed by writing unit :: Unit.

You can follow this in, If you like to do that, write in the following to give it a try:

a :: Unit
a = unit
  1. If you got (Void), you can’t win. The opponent has (absurd) to defeat you every time. This is useful to know because the sides may switch.

  2. forall a. b is a game where the opponent can select the game a and it gets substituted into the game b. You are required to provide a strategy to not lose in any of games that opponent might construct by replacing a with any type.

  3. The arrow (a -> b) means for a game where you retrieve a variable to initiate the game (a) with the opponent as many times as you want. You can use those plays to win in the game (b).

In the arrow-game, the opponent must supply a game (a) to obtain a play to the game (b). The game is supplied with the “apply” -syntax. Eg. If the (f)is valid play to (a -> b), and (x) is valid play to (a), then (f x) is valid play to (b).

Examples, here’s the “forall” and arrow together because they appear together a lot. The examples are examples of copycat strategies, you take an opponent’s play, and repeat it against himself:

c :: forall a. a -> a
c x = x

d :: forall a b. a -> b -> a
d x y = x

Also the game where the opponent can’t win may be interesting:

e :: forall a. Void -> a
e x = absurd x
  1. The record is a game where opponent may challenge you to play multiple games and you have to win them all. {x :: a, y :: b, z :: c} means you got games a, b and c. The opponent may select the game a with the label .x, and so on.

Below’s an example of a game where opponent is challenged to multiple games with you, here’s also something crucial you already saw earlier. You put the opponent to play against himself and he can’t do anything else but to lose.

h :: forall a b c. {x :: a, y :: b, z :: c} -> b
h record = record.y

Likewise to play such games, you got the record syntax to combine plays:

i :: {x :: Unit, y :: Int}
i = {x: unit, y: 4}

Now, if you understand this, next we can proceed for explanation of the Functor and the fat arrow (=>). We should verify that you understand these things before proceeding there though.

As an exercise, you could try to look at the lines starting with :: and see how far you get. Can you explain what kind of games they represent?

An another exercise, describe an always winning strategy for this game (this means same as giving it a definition that passes a type checker and can be guaranteed to terminate):

s :: forall a b c. (a -> b -> c) -> (a -> b) -> a -> c

Some additional help to building terms in If you do this:

s = ?hoo

You get a different error that looks like this:

Hole 'hoo' has the inferred type

  (a0 -> b1 -> c2) -> (a0 -> b1) -> a0 -> c2

Now you can start progressing with the solution:

s x = ?hoo

And you again get a different error:

Hole 'hoo' has the inferred type

  (a0 -> b1) -> a0 -> c2

in the following context:

  x :: a0 -> b1 -> c2

It’s very much like playing some sort of a game.

If you feel something needs further explanation, or it still needs to be simpler, please let me know. I’ll supply with all you need to understand this way to understand Purescript. Also if you feel like it’s a bit silly, well… This is not something I came up with. I learned this and have found this useful, but I may not know how to express how it is useful.

Update: I think it’s about semantics. There is a bunch of PDF slides that say game semantics are a form of denotational semantics. Types have multiple semantics and those can be used to understand what types mean.

Also, how do everybody else think about this? Would this be a good approach to explaining Purescript? I think this is being used to explain formal logic, and I think it does also work here. Or have I mixed it up more?

I might be biased because I already know get how Types work. However, if I was a new learner to PureScript, this explanation would have been hard for me to follow, mainly because of the “game” theme. I can see how using typed holes can feel like playing a game, but I don’t think that analogy is sound. Games can be played casually where the end-user is just wasting time and actually doesn’t care whether they win or not. Types are more like logic: X is inferred to be true because Y is true.

My current understanding of Types is that they represent a Set of values. For example, the type Boolean has two possible values: true and false. If I have a function, Boolean -> Boolean, it tells me two things:

  1. Only two possible values can be passed into that function
  2. Only two possible values can be outputted by that function.

As a result, I have a pretty good idea as to what this function does. It’s either not, where the argument is inverted, or identity, where the argument is outputted.

not :: Boolean -> Boolean
not true = false
not false = true

identity :: Boolean -> Boolean
identity theArgIsTheOutput = theArgIsTheOutput

In TypeScript, you annotate a value with the type to the right of it using a single colon:

valueName: Type = 4

In PureScript, you annotate a value with a type above it using two colons:

valueName :: Type
valueName = 4

Without the type annotation, PureScript looks like most other language:

valueName = 4

However, PureScript and Haskell emphasize types. Rather than writing something like this in Scala

// not sure whether this syntax is even correct
foo[F[_], A](arg: A, fa: F[A]) { 
  .. body .. 

We can separate the value-level code (i.e. where values and functions are implemented) from the type-level code (i.e what the corresponding type of the value is):

foo :: forall f a. a -> f a -> output
foo = -- body

This tends to make it easier to read the code when types get complicated.


I see each type as a set of values as you do but, just to clarify, your hypothetic function could be

constTrue :: Boolean -> Boolean
constTrue _ = true


constFalse :: Boolean -> Boolean
constFalse _ = false