Skip to content

Commit

Permalink
Make next major release: ps-0.14.x-v0.28.0 (#546)
Browse files Browse the repository at this point in the history
* Update spago to v0.19.0

* Bump page number of Getting Started files

I'm making space to split up the very long 'Why Learn PureScript' file 
into 3 files

* Split 'Why Learn PureScript' into 3 separate files

* Remove string parsers guide

* Remove optparser guide

* Remove tree guide

* Remove Node.ReadLine guide

* Remove Node.FS guide

* Remove HTTP guide

* Remove Parallel guide

* Remove Halogen guide

* Remove Libraries folder in Projects

* Remove Random Number game project (ported to its own repo)

* Remove Project/Libraries and Project/Random Number Game from CI

* Remove ToC generator Project

* Remove the Mdbook ToC Project

* Replace Projects with links to real projects I've created

* Link to projects again; link to new repos for my programs

* Move Type Classes folder to its own Appendix-like folder

* Remove Library Stacks part of Ecosystme folder

* Remove Performance-Related folder in Ecosystem folder

* Move Ecosystem/TLP file into type classes appendix folder

* Port sum/product types to corresponding spot in Basic Data Types

* Remove Ecosystem folder

* Rename Conclusion file to Next Steps

* Move list of projects into 'Next Steps' folder

* Unrecommend Free monad as approach to use when structuring programs

* Remove FAQ section still in Strenghts of PS file

* Remove Ecosystem from issue templates

* Remove Ecosystem prefix in front of file's name

* Remove Projects and Ecosystem folders from Preface

* Replace error with unsafeCrashWith

* Reorder Design Pattern files: simpler/basic first

* Add section on regular expressions and why FPers don't use them

* Bump top-level folder numbers for 0x folders

* Reorder syntax folder to open space for global instances file

* Clean up type classes overview in FP foundations

* Port Global Instances discussion to Syntax folder

I think it's better to discuss this in a file closer to where Newtypes 
are explained

* Remove package overrides

* No longer remove folders from old releases

* Attempt to update packages.dhall to v0.14.0 package set

* Update Basic Syntax folder with v0.14.0 PS syntax

* Update Type-Level Programming Syntax folder to ps v0.14.0

* Update module syntax to ps v0.14.x

* Update package set and CI to use v0.14.0-rc5

* Fix remaining syntax issues

* Remove Projects/ToC Generator folder from CI

* Temporarily override variant with ps-0.14-compatible fork

* Fix compiler error since toUpper isn't in scope by using other function

* Group GH Actions' logging together when building/testing project

* Use temporary fork of ps-0.14-compatible benchotron

* Fix type signature of prefixWithText

* Exclude generics-rep as dependency for spec

* No longer group build summary log lines

* Add ansi to package set

* Add rather than override packages

* Fix typo

* Temporarily use ps-0.14-compatible fork of spec

* Update quickcheck items to account for NonEmptyArray breaking changes

* Bump big picture file's index to new major index

* Bump files minor index to make room for new page

* Port graph reduction content to new file

* Remove the false 'description then interpretation' idea

* Fix typo

* Fix header level

* Add Optimizing Functions section to Equational Reasoning file

* Provide short preface to file

* Move Equational Reasoning file to be after type class file

Since laws are mentioned in the equational reasoning file, it should 
follow the type class file that first introduces that concept.

* Link to Algorithm Design with Haskell in multiple places

* Update build tools history with better summary of things

* Update package set; try another fork of spec

* Provide GitHub Actions example files for adding CI to PureScript repos

* Remove 'CLI-Programs - All Options Exampled' files

These have been out of date for quite some time and no one has opened an 
issue for them. It's a hassle to update these because new releases are 
made frequently, so it's easier to just stop maintaining this.

* Completely remove "Build Tools" file

* Add note: Bower registry is deprecated; community moving away from bower

* Update file indices in light of Build Tools file deletoin

* Reorder layout of table

* Include Harry's notes: install deps using bower due to registry issue

* Change when and how I explain using bower like spago

* Get test library to compile again by updating quickcheck

* Finish fixing package set

* Use latest tooling

* Update purescript and spago version references

* Fix file index: change minor back to 1

* Remove the 'install script'

* Remove the old ToC file now that we use mdbook

* Update package set to first official 0.14.0 set

* Update package set to latest tag

* Remove FProxy and SProxy usage

* Remove all usages of kind-specific Proxy types in favor or Proxy

* Add kind signatures to code

* Fix remaining compiler errors with updating run
  • Loading branch information
JordanMartinez committed Mar 5, 2021
1 parent a3bf470 commit f816862
Show file tree
Hide file tree
Showing 334 changed files with 1,109 additions and 36,982 deletions.
77 changes: 27 additions & 50 deletions .ci/spago--build-and-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,62 +11,81 @@

## Syntax

echo "::group::Basic Syntax"
cd 11-Syntax/01-Basic-Syntax/
pwd
spago build
SYNTAX_BASIC=$?
cd ../../
echo "::endgroup::"

echo "::group::Foreign Function Interface Syntax"
cd 11-Syntax/02-Foreign-Function-Interface/
pwd
spago build
SYNTAX_FFI=$?
cd ../../
echo "::endgroup::"

echo "::group::Type Level Programming Syntax"
cd 11-Syntax/03-Type-Level-Programming-Syntax/
pwd
spago build
SYNTAX_TLP=$?
cd ../../
echo "::endgroup::"

echo "::group::Module Syntax"
cd 11-Syntax/04-Module-Syntax/
pwd
spago build
SYNTAX_MODULE=$?
cd ../../
echo "::endgroup::"

echo "::group::Prelude Syntax"
cd 11-Syntax/05-Prelude-Syntax/
pwd
spago build
SYNTAX_PRELUDE=$?
cd ../../
echo "::endgroup::"

echo "::group::Rebindable Do/Ado Syntax"
cd 11-Syntax/06-Modifying-Do-Ado-Syntax-Sugar/
pwd
spago build
SYNTAX_DO_ADO_NOTATION=$?
cd ../../
echo "::endgroup::"

## Hello World

echo "::group::Hello World - Effect and Aff"
cd 21-Hello-World/02-Effect-and-Aff/
pwd
spago build
HELLO_EFFECT_AND_AFF=$?
cd ../../
echo "::endgroup::"

echo "::group::Hello World - Debugging"
cd 21-Hello-World/03-Debugging/
pwd
spago build
HELLO_DEBUGGING=$?
cd ../../
echo "::endgroup::"

echo "::group::Hello World - Collections and Loops"
cd 21-Hello-World/04-Collections-and-Loops
pwd
spago build
HELLO_COLLECTIONS_LOOPS=$?
cd ../../
echo "::endgroup::"

echo "::group::Hello World - Application Structure"
cd 21-Hello-World/05-Application-Structure/
pwd
spago build
Expand All @@ -90,14 +109,17 @@ spago run -m Examples.NumberComparison.Run
HELLO_EXAMPLE_NUMBER_COMPARISON_RUN=$?

cd ../../
echo "::endgroup::"


echo "::group::Hello World - Type Level Programming"
cd 21-Hello-World/06-Type-Level-Programming/
pwd
spago build
HELLO_TLP=$?
cd ../../
echo "::endgroup::"

echo "::group::Hello World - Testing"
cd 21-Hello-World/07-Testing/
pwd
# This folder includes tests that are designed to fail. So, rather than
Expand All @@ -108,46 +130,15 @@ pwd
spago build
HELLO_TESTING=$?
cd ../../
echo "::endgroup::"

echo "::group::Hello World - Benchmarking"
cd 21-Hello-World/08-Benchmarking/
pwd
spago build
HELLO_BENCHMARK=$?
cd ../../

cd 22-Projects/01-Libraries
pwd
# Build but do not run benchmark tests
spago build
PROJECTS_LIBRARIES_BUILT_OK=$?
cd ../../

cd 22-Projects/11-Random-Number-Game
pwd
# Build but do not run benchmark tests
spago build
PROJECTS_RANDOM_NUMBER_GAME=$?

# Node-based tests
spago test -m Test.RandomNumber.ReaderT.Standard.DifferentMonad
PROJECTS_RANDOM_NUMBER_GAME_TEST_READERT_DIFFERENT=$?
spago test -m Test.RandomNumber.ReaderT.Standard.SameMonad
PROJECTS_RANDOM_NUMBER_GAME_TEST_READERT_SAME=$?
cd ../../

cd 22-Projects/12-ToC-Generator
pwd
# Build but do not run benchmark tests
spago build
PROJECTS_TOC_GENERATOR=$?

# Node-based tests
# spago test -m Test.ToC.MainLogic.QuickCheckTest
echo "Skipping 'ToC.MainLogic.QuickCheckTest' due to bug that I will fix later."
PROJECTS_TOC_GENERATOR_TEST_MAIN_LOGIC_BOTH=$?
spago test -m Test.ToC.ParserLogic.QuickCheckTest
PROJECTS_TOC_GENERATOR_TEST_PARSER_LOGIC_BOTH=$?
cd ../../
echo "::endgroup::"

echo ""
echo "Finished. Summarizing Results:"
Expand All @@ -171,13 +162,6 @@ echo "$HELLO_EXAMPLE_NUMBER_COMPARISON_RUN - Hello World - Application Structure
echo "$HELLO_TLP - Hello World - Type-Level Programming"
echo "$HELLO_TESTING - Hello World - Testing"
echo "$HELLO_BENCHMARK - Hello World - Benchmarking"
echo "$PROJECTS_LIBRARIES_BUILT_OK - Projects - Libraries"
echo "$PROJECTS_RANDOM_NUMBER_GAME - Projects - RandomNumber"
echo "$PROJECTS_RANDOM_NUMBER_GAME_TEST_READERT_DIFFERENT - Projects - RandomNumber - ReaderT Test (Different)"
echo "$PROJECTS_RANDOM_NUMBER_GAME_TEST_READERT_SAME - Projects - RandomNumber - ReaderT Test (Same)"
echo "$PROJECTS_TOC_GENERATOR - Projects ToC"
echo "$PROJECTS_TOC_GENERATOR_TEST_MAIN_LOGIC_BOTH - Projects - ToC - Main - Both"
echo "$PROJECTS_TOC_GENERATOR_TEST_PARSER_LOGIC_BOTH - Projects - ToC - Parser - Both"

if [ $SYNTAX_BASIC == 0 ] &&
[ $SYNTAX_FFI == 0 ] &&
Expand All @@ -197,14 +181,7 @@ if [ $SYNTAX_BASIC == 0 ] &&
[ $HELLO_EXAMPLE_NUMBER_COMPARISON_RUN == 0 ] &&
[ $HELLO_TLP == 0 ] &&
[ $HELLO_TESTING == 0 ] &&
[ $HELLO_BENCHMARK == 0 ] &&
[ $PROJECTS_LIBRARIES_BUILT_OK == 0 ] &&
[ $PROJECTS_RANDOM_NUMBER_GAME == 0 ] &&
[ $PROJECTS_RANDOM_NUMBER_GAME_TEST_READERT_DIFFERENT == 0 ] &&
[ $PROJECTS_RANDOM_NUMBER_GAME_TEST_READERT_SAME == 0 ] &&
[ $PROJECTS_TOC_GENERATOR == 0 ] &&
[ $PROJECTS_TOC_GENERATOR_TEST_MAIN_LOGIC_BOTH == 0 ] &&
[ $PROJECTS_TOC_GENERATOR_TEST_PARSER_LOGIC_BOTH == 0 ]
[ $HELLO_BENCHMARK == 0 ]
then
echo "Build Succeeded"
exit 0;
Expand Down
16 changes: 0 additions & 16 deletions .ci/spago--install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,4 @@ npm install benchmark
spago install
cd ../../

cd 22-Projects/01-Libraries
pwd
spago install
cd ../

cd 22-Projects/11-Random-Number-Game
pwd
npm install benchmark
spago install
cd ../

cd 22-Projects/12-ToC-Generator
pwd
spago install
cd ../

echo "... Finished ...."
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ Getting Started
Build Tools
Syntax
Design Pattern
Ecosystem

2. Indicate what kind of issue this is

Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ jobs:

- name: Set up PureScript toolchain
uses: purescript-contrib/setup-purescript@main
with:
purescript: "0.13.8"
spago: "0.16.0"

- name: Cache PureScript dependencies
uses: actions/cache@v2
Expand Down
94 changes: 94 additions & 0 deletions 01-Getting-Started/01-Why-Learn-PureScript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Why Learn PureScript?

All languages make tradeoffs in various areas and on various spectrums:
- learning curve
- abstractions
- syntax
- errors
- type systems
- etc.

The question is "Which combination of tradeoffs provides the most benefits in prioritized areas?" "Good" languages happen to select specific tradeoffs that make the language well-suited for specific problems. For example, Python is well-suited for creating dirty one-time-run scripts to do tedious work on a computer. While Python can be used to create a financial or medical applications that need to extremely fast and secure, it would be better to use a different language that is better suited for such a task, such as Rust.

PureScript has chosen tradeoffs that its developers think are the best for creating simple to complex front-end applications that "just work;" that are easy to refactor, debug, and test; and help make developers more productive rather than less.

It can be said that other front-end languages buy "popularity" at the cost of "power and productivity."
PureScript buys "power and productivity" at the cost of "popularity."

To fully answer "Why learn PureScript?" we must answer three other questions:
- Why one should use Javascript to build programs...
- ...but not write Javascript to build it...
- ...and write Purescript instead of alternatives

## Why one should use Javascript to build programs...

- The web browser is the new ["dumb terminal"](https://www.youtube.com/embed/YI34UIMgkxs?start=1762&end=1828) / platform-independent OS:
- [What can web do today?](https://whatwebcando.today/)
- [Why Founders Should Start With a Website, Not a Mobile App](https://www.atrium.co/blog/founders-should-build-website-not-mobile-app/)
- The points mentioned in this article: [Learn Javascript in 2018](https://web.archive.org/web/20181201032915/https://medium.com/zerotomastery/learn-to-code-in-2018-get-hired-and-have-fun-along-the-way-b338247eed6a)

## ...but not write Javascript to build it...

- [JavaScript is a Dysfunctional Programming Language](https://medium.com/javascript-non-grata/javascript-is-a-dysfunctional-programming-language-a1f4866e186f)
- [Top 10 Things Wrong with JavaScript](https://medium.com/javascript-non-grata/the-top-10-things-wrong-with-javascript-58f440d6b3d8)
- [Why JavaScript Sucks](https://whydoesitsuck.com/why-does-javascript-suck/)

Some other ideas that are relevant:
- dynamic typing leads to errors that do not appear until after you have already shipped the code to your customers
- a linter is just a basic static type checker
- it is sometimes easier to write, read, and understand a 'safer language' that compiles to efficient Javascript than to write, read, and understand JavaScript itself (as the above articles show)

## ...and write Purescript instead of alternatives

**TL;DR**

- [The Power of Composition](https://youtu.be/vDe-4o8Uwl8?t=8)
- [Purescript: Tomorrow's Javascript Today](https://www.youtube.com/watch?time_continue=22&v=5AtyWgQ3vv0)
- [Code Reuse in PureScript: Functions, Type Classes, and Interpreters](https://youtu.be/GlUcCPmH8wI?t=24)
- [Phil Freeman's post: 'Why You Should Use PureScript'](https://gist.github.com/paf31/adfd15fbb1ac8b99fc68be2c9aca8427)
- PureScript's "Real World App"s
- See the [Halogen version of 'Real World App'](https://github.com/thomashoneyman/purescript-halogen-realworld)
- See the [React version of 'Real World App'](https://github.com/jonasbuntinx/purescript-react-realworld)
- [A Discourse pose describing some of the disadvantages of TypeScript and Elm when compared to PureScript](https://discourse.purescript.org/t/language-highlights/1471)

### Language Comparisons

For a full list of possible alternatives to JavaScript, see [CoffeeScript's wiki's list of 'Languages that compile to JavaScript'](https://github.com/jashkenas/coffeescript/wiki/List-of-languages-that-compile-to-JS)

**Note**: the below comparisons are still a WIP. To fully support this claim, it would help to compare each languages' various "overall rating" on various aspects. Unfortunately, since I'm not familiar with every other language mentioned, it's very difficult for me to do that. If you are familiar with such languages, consider opening an issue on this repo and discussing it with me.

In short, the below comparison will be biased towards PureScript and will not yet fairly represent the corresponding side in some situations. Consider this a starting point for your own research.

#### PureScript vs TypeScript

One of the main issues with JavaScript is a poor type system. Many errors aren't discovered until a person, usually a customer, runs the program. Many of these same errors could be detected and fixed before shipping code if one used a language with a better type system.

TypeScript seems to address this type safety issue. Just consider its name! However, a few people who are using PureScript now have said this about TypeScript: "You might as well be writing Javascript." TypeScript does not provide any real guarantees; it only pretends. PureScript does provide such guarantees.

- [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)

#### PureScript vs Elm

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
- ... 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.

#### PureScript vs OCaml / Reason

This section has not yet been written.

#### PureScript vs GHCJS

Haskell, which heavily influenced PureScript, has an option for compiling Haskell to JavaScript via GHCJS. However, that comes with its own tradeoffs. PureScript was developed partly because those tradeoffs were too costly.

See [PS or ghcjs for Frontend with Haskell backend](https://discourse.purescript.org/t/ps-or-ghcjs-for-frontend-with-haskell-backend/666/2) for my summary of the main issues at play here.
56 changes: 56 additions & 0 deletions 01-Getting-Started/02-The-Strengths-of-PureScript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# The Strengths of PureScript

In this file, I'll cover what some of the tradeoffs PureScript makes are and why they are good. These ideas will be further explained in the "FP Philosophical Foundations" folder that appears later in this repository.

## Strongly Adheres to the Functional Programming Paradigm

- [A Secret Weapon for Startups -- Functional Programming?](https://www.ramanan.com/personal-blog/2019/2/25/functional-programming-and-venture-capital)
- Paradigm shifts, such as the one demonstrated by this video using C++, are what enable programs with less problems: [Logging a function's name each time it is called: migrating an "object-oriented paradigm" solution to an "functional paradigm" solution](https://www.youtube.com/embed/i9CU4CuHADQ?start=540). As will be explained later, this is what is known as the "Writer Monad."
- [Object-oriented "design patterns" in FP languages](http://blog.ezyang.com/2010/05/design-patterns-in-haskel/) are often just functions in disguise. Rather than learning the 20 different design patterns, one can learn how functions work and can be used to create really beautiful concepts and solutions.
- [Functional Architecture: The Pits of Success](https://www.youtube.com/watch?v=US8QG9I1XW0). To summarize this video, FP languages force you to structure your code in a way that makes it:
- easy to test in an unbiased way (Can I prove that the logic/algorithm that solves the business problem is correct and works according to the specification despite any programmer's laziness or lack of foresight in thinking of a possible scenario where the code could fail?)
- easy to add/change/remove a "backend" to account for trends, new insights, or faster code (Without introducing a new bug or deleting a current feature, can I switch from Company A's database to Company B's database without rewriting more than 30 lines of code?)
- unconcerning to allow a new developer to work on the code, knowing that he/she cannot screw up anything major (Can the Lead/Senior Developer take the weekend off and return, knowing that it's extraordinarily difficult for developers with little experience to break something?)

## Powerful Static Type System

- This video explains how a type system with `algebraic data types` comes with a number of benefits (note: it uses a different syntax than PureScript: [Domain Modeling Made Functional](https://www.youtube.com/watch?v=Up7LcbGZFuo). To summarize it, `algebraic data types`
- allow you to model a domain at a 1-to-1 ratio
- make impossible states impossible
- become your always-up-to-date UML diagrams
- make it easy for new developers to learn how the code is structured
- guide how business logic should be implemented
- The PureScript compiler infers most of your types for you. For those who are curious and want to understand how that works, see this video: [Type Inference From Scratch](https://www.youtube.com/watch?v=ytPAlhnAKro)
- The compiler (via its warning and error messages) is your friend, not your enemy. It
- prevents you from releasing bug-filled code to a customer. (Can I guarantee that the code "just works" or cannot be built at all?)
- forces you to handle most errors correctly the first time rather than permit you to throw them under the rug because you are lazy (Can I guarantee all possible errors will not create future problems that lead to short-term hard-to-understand code that rarely gets cleaned up and ultimately costs the company more time to fix than if it had just been written correctly the first time?)
- helps you figure out how to implement functions correctly via "Typed Holes" (explained later in the `Syntax` folder)
- This video explains how a type system with `type classes` allow one to re-use "dumb old data structures" (i.e. `algebraic data types`) rather than create many new data structures that differ only one slight way: [Type Classes vs the World](https://www.youtube.com/watch?v=hIZxTQP1ifo). To summarize it, `type classes`
- allow you to write declarative code ("this is what will be true") rather than imperative code ("this is how to make truth true (hopefully, you got it right)")
- enables the compiler to infer runtime code

## Immutable Persistent Data Structures by Default

In PureScript, immutable data structures are the default rather than being "opt-in." In most other languages, mutable data structures are the default with immutable ones being "opt-in."

Immutable data structures are
- easier to reason about because the value never changes
- are always thread-safe, preventing many typical issues with concurrency
- can be as performant as mutable data structures in most cases

## Multiple Backends with Easy Foreign Function Interface

Most languages have their own backend.
- Javascript is compiled and run via a Javascript engine.
- Java compiles to bytecode that can be run on a Java Virtual Machine.
- Python gets compiled into bytecode that is then interpreted.

PureScript does not have a backend. Rather, it's source code can be compiled to other languages. While JavaScript is the focus, [PureScript compiles to other languages besides JavaScript](https://github.com/purescript/documentation/blob/master/ecosystem/Alternate-backends.md). Thus, writing one library in PureScript can work in multiple languages, and one can choose the backend (or a combination of them) that best solves their problem.

Caveat: PureScript's support for non-Javascript backends is still a work-in-progress. In future releases, they will be getting first-class support.

This backend-independent nature of PureScript makes "Foreign Function Interface" very clean. At various times, Language X needs to use code from another language, Language Y. For code written in one language to use code written in another language, there needs to be a "Foreign Function Interface" or FFI.

Many languages' FFI can be difficult to work with. Language X made various language tradeoff decisions that are different than Language Y. Getting two languages to work together is difficult to say the least. However, PureScript's FFI is very easy because PureScript already compiles to that language.

If you are compiling PureScript to Javascript, you can still write JavaScript as FFI for PureScript. This makes it possible to wrap Javascript libraries on which you heavily depend. It also enables one to easily migrate from some other language or framework (e.g. TypeScript, Angular, etc.) to PureScript in a modular, piece-by-piece fashion

0 comments on commit f816862

Please sign in to comment.