Skip to content

Commit

Permalink
Make next major release: ps-0.15.x-v0.32.0 (#603)
Browse files Browse the repository at this point in the history
* Fix typo in higher kinded data pattern

* Upgrade to PS 0.15.2 and package set

* Add recursive type workaround with newtype example

* Document typed holes on bindings tip/trick

* Add entry for `purs-backend-es` and its library

* Update example CI files

* Cleanup immutability & persistence section via MermaidJs

* Update project to 0.15.4; update esbuild

* Also recommend `purs-backend-es` as optional tooling

* Cleanup the WriterT/ExceptT overviews

* Add another page for state-like transformers

* Update preface's version of PureScript

* Link to PS+Halogen > TS+React

* Update PS to 0.15.7; node to 16

* Simplify installation section

* Replace Atom instructions with VS Code ones

* Update elm section to include Gren

* Add repl Gotchas

* Remove old note about `0.11.7` release

* Include Unfoldable as another loop type class

* Provide better type class examples

* Add pronunciation

* Add purescript-psa to recommended tooling

* Link to Thomas' recommended tooling post

* Update CI versions

* Fix typo. Recommend purs-tidy

* Add missing whitespace

* Rename ctors for clarity

* Clarify pattern guard syntax

* Add note about type alias inlining gotcha

* Correct recursive part of let/where blocks

* Clarify indentaton convention

* Clarify binding indentation rules

* Relocate/rename typeclass & newtype files

* Add box example to newtyped instance

* Move Newtype class deriving to own file

* Fix duplicate function: rename function

* Demonstrate what Generic rep's value is

* Relocate Special Type Classes folder

* Add type signature to emojiKey example

* Fix broken link

* Link to TS to PS migration guide

* Show linked-list structure of Generics

* Fix some FFI examples, add uncurried one

* Link to artemis' qualified-do package

* Break out types overview to own page; add small visual

* Combine files into one about functions

* Note that Foldable/Traversable are now derivable

* Update package set; update benchotron

* Update benchmark readme to use my fork

* Update version in preface to 0.15.7
  • Loading branch information
JordanMartinez committed Dec 30, 2022
1 parent 96577f7 commit ae89283
Show file tree
Hide file tree
Showing 73 changed files with 1,882 additions and 480 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up PureScript toolchain
uses: purescript-contrib/setup-purescript@main
with:
purescript: "0.15.4"
purescript: "0.15.7"

- name: Cache PureScript dependencies
uses: actions/cache@v2
Expand All @@ -40,7 +40,7 @@ jobs:
- name: Set up Node toolchain
uses: actions/setup-node@v2
with:
node-version: "14"
node-version: "16"

- name: Install dependencies
run: |
Expand Down
10 changes: 6 additions & 4 deletions 01-Getting-Started/01-Why-Learn-PureScript.md
Expand Up @@ -68,20 +68,22 @@ TypeScript seems to address this type safety issue. Just consider its name! Howe
- [TypeScript vs PureScript: Not All Compilers Are Created Equal](https://blog.logrocket.com/typescript-vs-purescript-not-all-compilers-are-created-equal-c16dadaa7d3e)
- [JavaScript, TypeScript, and PureScript](https://www.youtube.com/watch?v=JTEfpNtEoSA) or "Why TypeScript only 'pretends' to have types."
- [Various examples comparing PureScript and TypeScript](https://discourse.purescript.org/t/type-system-showdown-purescript-and-typescript/2084)
- [Experience Report: PureScript+Halogen > TypeScript+React](https://web.archive.org/web/20221026181022/https://twitter.com/christopherdone/status/1572329195858018307)
- [A Guide on Migrating from TypeScript to PureScript](https://github.com/xc-jp/blog-posts/blob/master/_posts/2021-10-07-PureScript-React.md)

#### PureScript vs Elm
#### PureScript vs Elm / Gren

Since Elm is founded on the similar philosophical foundations as PureScript, one can use Elm and gain many of the same benefits as PureScript due to its type safety. However, there is a ceiling on the abstractions one can express in Elm. PureScript's ceiling is much higher than Elm's because it has type classes.
[Elm](https://elm-lang.org/) is a language founded on the similar philosophical foundations as PureScript. [Gren](https://gren-lang.org/) is a fork of Elm by the community. Whichever one is used, one can gain many of the same benefits as PureScript due to its type safety. However, there is a ceiling on the abstractions one can express. PureScript's ceiling is much higher than Elm's because it has type classes.

Elm
Elm/Gren
- ... sacrifices the following features ...
- type classes, which
- reduce boilerplate code since the compiler can write code for you
- enable one to define and uphold constraints about their program (e.g. this sequence of commands must be executed in the correct order)
- ... to gain the following ...
- clear actionable error messages because there are less ambiguous cases to deal with in the type system

Elm and PureScript can both be used to build a complex website. However, one will need to write more lines of code in Elm than they would in PureScript.
Elm, Gren, and PureScript can both be used to build a complex website. However, one will need to write more lines of code in Elm or Gren than they would in PureScript.

#### PureScript vs OCaml / Reason

Expand Down
69 changes: 15 additions & 54 deletions 01-Getting-Started/04-Install-Guide.md
Expand Up @@ -13,10 +13,14 @@ Throughout your learning process, it will be helpful to ask others for help. The
### Overview

We'll show how to install the following programs:
- `purescript` - the PureScript language & compiler
- `spago` - a dependency manager and build tool for PureScript
- (optional) a formatter for PureScript
- `parcel` - a build tool for bundling a PureScript application into a multiple JS backends (node, browser, electron)
- [`purescript`](https://github.com/purescript/purescript) - the PureScript language & compiler
- [`spago`](https://github.com/purescript/spago/) - a dependency manager and build tool for PureScript
- [`esbuild`](https://esbuild.github.io/) - a build tool for bundling a PureScript application into a multiple JS backends (node, browser)
- (optional, recommended) [`purescript-psa`](https://www.npmjs.com/package/purescript-psa) - pretty-prints compiler warnings/errors with stats; promotes compiler warnings to errors
- (optional, recommended) [`purs-tidy`](https://www.npmjs.com/package/purs-tidy) - a formatter for PureScript
- (optional, recommended) [`purs-backend-es`](https://github.com/aristanetworks/purescript-backend-optimizer) - a tool for producing optimized JavaScript code from the compiler's output.

Thomas Honeyman, a core contributor to PureScript, usually posts an annual ["Recommended Tooling for PureScript in <year>"](https://discourse.purescript.org/t/recommended-tooling-for-purescript-in-2022/3206). At the time of writing, this one was for 2022.

### Installation

Expand All @@ -26,13 +30,10 @@ We can install everything using `npm`. However, getting `npm` is it's own proble

##### Manual Install

Justin Woo explains how to set up one's environment for the `0.12.x` release but has not been updated for two things. First, the PureScript release at the time was `0.12.0` but now `0.13.8` is out. Second, the instructions use `pulp` and `psc-package`, a different build tool workflow than the one we'll use here.

If you just want to get things set up ASAP, follow the below summary of his article's instructions (using `spago` instead of the other tools). If you want to understand why you should do these commands, read [his article here](https://qiita.com/kimagure/items/570e6f2bbce5b4724564):
1. Install Node 14 or greater: https://nodejs.org/en/download/
1. Install Node 16 or greater: https://nodejs.org/en/download/
2. Set your npm prefix: `npm set prefix ~/.npm`
- Note: this prevents having to use `sudo` when using NPM to install things since it's default prefix is in a place that requires admin privileges
3. Set your PATH: `export PATH="$HOME/.npm/bin:$PATH"`
3. Set your PATH: `export PATH="$PATH:$HOME/.npm/bin"`

##### NVM Install

Expand All @@ -47,13 +48,9 @@ Unlike the manual install, `nvm` properly handles the npm prefix for you. So, yo
Once you have installed `npm`, we can use it to install everything in one command:

```sh
npm i -g purescript@0.15.4 spago@0.20.9 esbuild@0.15.7
npm i -g purescript@0.15.7 spago@0.20.9 esbuild@0.15.7 purs-tidy@0.9.2 purs-backend-es@1.3.1 purescript-psa@0.8.2
```

If you want to install a PureScript formatter, refer to their instructions. The history behind these tools will be covered in the `Build Tools` folder:

- [purs-tidy](https://github.com/natefaubion/purescript-tidy) - A self-contained formatter written in PureScript
- [pose](https://pose.rowtype.yoga/) - A plugin written in PureScript for the [`Prettier`](https://prettier.io/) formatter

If you want to produce optimized JavaScript for your production environment (rather than a developer environment), install [`purs-backend-es`](https://github.com/aristanetworks/purescript-backend-optimizer):

Expand All @@ -66,7 +63,7 @@ npm i -g purs-backend-es
The following commands should now work:

```sh
purs --version # 0.15.4
purs --version # 0.15.7
spago --version # 0.20.9
esbuild --version # 0.15.7
```
Expand All @@ -91,50 +88,14 @@ Whenever I make a new release with breaking changes, this script will remove any

### Setting up your editor

The following are instructions for setting up the Atom editor. For Emacs, Vim, or Visual Studio, [consult Justin Woo's post on the matter](https://qiita.com/kimagure/items/570e6f2bbce5b4724564#install-some-editor-plugins) and [the respective page in the documentation repo](https://github.com/purescript/documentation/blob/master/ecosystem/Editor-and-tool-support.md#emacs)
The following are instructions for setting up the VS Code editor. For other editors, see [the respective page in the documentation repo](https://github.com/purescript/documentation/blob/master/ecosystem/Editor-and-tool-support.md#emacs)

Atom setup instructions:
1. Install Atom: `sudo apt-get install atom`
2. Launch Atom and install the following packages:
1. Install VS Code
2. Launch VS Code and install the following packages:
- ide-purescript
- atom-ide-ui
- language-purescript
3. Configure `ide-purescript`

The Atom package, `ide-purescript`, is configured to `Bower`, but we'll be using `spago` as our dependency manager for this project. Follow these instructions
1. Open Atom's settings dialog (`CTRL+,`)
2. Click on the `Packages` tab
3. Search for `ide-purescript`
4. Click on the `Settings` button in the entry that appears
5. Check the `Add spago sources` checkbox
6. Change the `build command` to: `spago build -u --json-errors`

### Getting IDE support (autocomplete, documentation-on-hover, etc.) in Atom

While this repository's contents are useful for learning various lessons, IDE support (autocomplete, documentation, etc.) will only work if you open this repository's contents in a specific way when using Atom. Follow the instructions below:
1. Click "File" and click "Open Folder..." (shortcut: `CTRL+O`)
2. In the folder chooser, choose one of this repo's project folders (i.e. a folder with a `spago.dhall` file and `src` folder)
3. Click on "Packages" and click on "PureScript" and then on "Build". The IDE server will start running and rebuild just that project.*
- Autocomplete, importing, and documentation will now work.

* This is a command you will use frequently, so consider adding a keyboard shortcut for it.
1. Open the Atom settings dialog (`CTRL+,`)
2. Click on the "KeyBindings" tab
3. Click on the "your keymap file" hyperlink that appears before the bindings
4. Follow the instructions for adding your personal shortcut for the `ide-purescript:build` command.

For mine, I did:
```cson
'.platform-linux atom-workspace atom-text-editor:not([mini])':
'ctrl-shift-b': 'ide-purescript:build'
```

#### Dealing with IDE Server issues in Atom

Sometimes when editing a file, the IDE server will go out-of-sync. For example, you might change the definition of a type and the IDE doesn't realize that occured, so it will tell you that you have used a type incorrectly. In such cases, rebuild the project using Step 3 (or your keyboard shortcut) above and things should correct themselves from there.

In situations where I have used the same names for things, the autocomplete might actually import a function or type with the same name as the one you want but from a different module. So, if you have weird compiler errors, check the imports to insure the IDE server didn't accidentally import something incorrect or from the wrong location.

## Setting up Module Linker

When you're browsing through code on GitHub, the browser extenstion, Module Linker, can greatly help:
Expand Down
15 changes: 10 additions & 5 deletions 01-Getting-Started/05-The-REPL.md
Expand Up @@ -39,11 +39,11 @@ In general, there are five things you can do in the REPL:

Sometimes, the REPL will output errors. These errors may not be immediately understandable for new learners, so the table below will help you understand them and know what to do.

| The Error | Its Meaning | What to do |
| - | - | - |
| "No type class instance was found for `Data.Show.Show [Type]`" | An expression cannot be turned into a `String`. For example, a function's implementation (`(\x -> x + 1)`) cannot be turned into a `String` whereas a value (`5`) or expression (`10 + 10`) can be (`5` and `20`, respectively). | If it's possible for you to define one, define an instance of the `Show` type class. If not, then ignore it and move on.
| "Multiple value declarations exist for [binding]." | You defined the binding twice, which you cannot do | See [the Reload command section](#reload) for what your options are |
| "Unknown operator (+)" | The `+` function was not imported because the `Prelude` module was imported | Import the Prelude module by typing `import Prelude` followed by pressing Enter. |
| The Error | Its Meaning | What to do |
| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| "No type class instance was found for `Data.Show.Show [Type]`" | An expression cannot be turned into a `String`. For example, a function's implementation (`(\x -> x + 1)`) cannot be turned into a `String` whereas a value (`5`) or expression (`10 + 10`) can be (`5` and `20`, respectively). | If it's possible for you to define one, define an instance of the `Show` type class. If not, then ignore it and move on. |
| "Multiple value declarations exist for [binding]." | You defined the binding twice, which you cannot do | See [the Reload command section](#reload) for what your options are |
| "Unknown operator (+)" | The `+` function was not imported because the `Prelude` module was imported | Import the Prelude module by typing `import Prelude` followed by pressing Enter. |

## A Quick Overview of Some of the REPL Commands

Expand Down Expand Up @@ -214,3 +214,8 @@ Type :? for help
Unexpected or mismatched indentation at line 3, column 1
```

## Other Gotchas

- `do notation` (covered later) is not supported in the REPL
- The REPL works by converting the PureScript code into a new program and running it on Node each time. Thus, using a monad like `Effect` and `let x = unsafePerformEffect (randomInt 1 10)` will not store a random number in the variable `x` that stays the same after that point. Rather, `x` will have a new number each time one inputs a new expression and runs it by pressing ENTER.
1 change: 0 additions & 1 deletion 01-Getting-Started/06-Other-Important-Info.md
Expand Up @@ -46,7 +46,6 @@ Then, you use a search query like the following:
- Pros: Only provides documentation for packages in the latest package set
- Cons: One does not immediately know which version of a library is displayed, nor what its dependencies are.
- Read [Pursuit's Search Help page](https://pursuit.purescript.org/help/users#searching)
- Some libraries have not been updated to `0.13.8` and are still on the `0.11.7` release. Some still work; others won't. In this work, we will insure that you do not use any such libraries, but be aware of that if you browse the docs on your own.
- Lastly, some libraries have not uploaded their latest versions' documentation. In these cases, we will forewarn you. Fortunately, `spago docs` will produce a local version of the source code's documentation that looks similar to Pursuit. It does not support all the features of Pursuit, but it's better than nothing. To do that, follow these commands:
- `spago docs --open` will generate the documentation and then use your default web browser to open the file, `generated-docs/html/index.html`.

Expand Down
Expand Up @@ -139,7 +139,7 @@ Just 1

## Other Loops

The following Purescript examples are very _crude_ ways of mimicking the following loops. More appropriate examples would require explaining and using type classes like `Foldable` and `Monad` (intermediate FP concepts). Thus, take these examples with a grain of salt.
The following Purescript examples are very _crude_ ways of mimicking the following loops. More appropriate examples would require explaining and using type classes like `Foldable`, `Unfoldable`, and `Monad` (intermediate FP concepts). Thus, take these examples with a grain of salt.

### While

Expand Down
24 changes: 20 additions & 4 deletions 02-FP-Philosophical-Foundations/06-Type-Classes.md
Expand Up @@ -48,13 +48,29 @@ Thus, type classes abstract general concepts into an "interface" that can be imp
### Examples

Here are some examples that demonstrate the combination of the 2-3 elements from above:
- The `Eq` type class specifies a type signature for a function called `eq`/`==` and `notEq`/`/=`, and laws for the two (e.g. if `a == b` and `b == c`, then `a == c`), but there are not any derived functions.
- The `Ord` type class is similar to `Eq`, but it does have derived functions.
- The `Functor` type class (explained in more detail later) has all three.
- The `Eq` type class.
- Required type signatures:
- `eq :: a -> a -> Boolean` (Note: `a == b` is the same as `eq a b`)
- Laws
- Reflexivity: `x == x`
- Symmetry: if `x == y`, then `y == x`
- Transitivity: if `x == y` and `y == z`, then `x == z`
- Derived Functions
- `notEq`, which inverts the result of `eq`: `notEq a b = not (a == b)`
- The `Monoid` type class
- Required type signatures:
- `append :: a -> a -> a` (Note: `a <> b` is the same as `append a b`)
- `mempty :: a`
- Laws
- Left unit: `(mempty <> x) == x` (Note: `0 + 1 == 1` is an example of this idea)
- Right unit: `(x <> mempty) == x` (Note: `"hello" <> "" == "hello"` is an example of this idea)
- Derived Functions
- `power :: a -> Int -> a`: append a value to itself N times (e.g. `power "a" 4 == "aaaa"`)
- `guard :: Boolean -> a -> a`: return either the `a` or `mempty` (e.g. `guard false "a" == ""` and `guard true "a" == "a"`)

## Similarities and Dual Relationships Among Type Classes

Some type classes have a corresponding "dual." While there are better ways to explain duals, the basic idea is that the "direction" of the function's arrow gets flipped. When this happens, we usually prefix them with "Co". For example, if we have a type class called `Monad`, the dual of it is called `Comonad`. If `Monad` has laws `A` and `B`, then it's likely that `Comonad` will have laws `A'` and `B'`, which are "flipped" version of `A` and `B`.
Some type classes have a corresponding "dual". While there are better ways to explain duals, the basic idea is that the "direction" of the function's arrow gets flipped. When this happens, we usually prefix them with "Co". For example, if we have a type class called `Monad`, the dual of it is called `Comonad`. If `Monad` has laws `A` and `B`, then it's likely that `Comonad` will have laws `A'` (pronounced "A-prime") and `B'` (pronounced "B-prime"), which are "flipped" version of `A` and `B`.

For example, a function like `toB` would have its arrow flipped to produce `toA`::

Expand Down
15 changes: 8 additions & 7 deletions 03-Build-Tools/04-Continuous-Integration.md
Expand Up @@ -25,13 +25,13 @@ jobs:

- uses: purescript-contrib/setup-purescript@main
with:
purescript: "0.15.4"
purs-tidy: "0.8.2"
psa: "0.7.2"
purescript: "0.15.7"
purs-tidy: "0.9.2"
psa: "0.8.2"

- uses: actions/setup-node@v
with:
node-version: "14"
node-version: "16"

- name: Install dependencies
run: |
Expand Down Expand Up @@ -82,8 +82,9 @@ jobs:

- uses: purescript-contrib/setup-purescript@main
with:
purescript: "0.15.4"
purs-tidy: "0.8.2"
purescript: "0.15.7"
purs-tidy: "0.9.2"
psa: "0.8.2"
spago: "0.20.9"
psa: "0.7.2"

Expand All @@ -98,7 +99,7 @@ jobs:
- name: Set up Node toolchain
uses: actions/setup-node@v2
with:
node-version: "14"
node-version: "16"

- name: Cache NPM dependencies
uses: actions/cache@v2
Expand Down

0 comments on commit ae89283

Please sign in to comment.