Skip to content

Commit

Permalink
Resolve a number of easy long-standing issues (#503)
Browse files Browse the repository at this point in the history
* Fixes #488: Clean up explanation behind `log` type signature

* Fix #491: should be 'yesK and noK', not 'yesK and yesK'

* Address #497: fix typo

* Fix #497: clarify REPL's `loaded` and `import` differences

* Fix #482: link to discourse post comparing PureScript to other TS and Elm

* Fix #483: link to Alexis King's "Effects for Less" video

* Fix #489: link to Kmett's Recursion Schemes: A Field Guide

* Link to React version of Real World App

* Describe the problem Generics solve and link to hdgarrood's explanation

* Fix #501: include '.' as a infix alias when not used alone

* Update ToC

* Update Changelog
  • Loading branch information
JordanMartinez committed Aug 22, 2020
1 parent 7c0ee58 commit 810c315
Show file tree
Hide file tree
Showing 12 changed files with 1,374 additions and 1,300 deletions.
5 changes: 4 additions & 1 deletion 00-Getting-Started/01-Why-Learn-PureScript.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ Some other ideas that are relevant:
- [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)
- See the [Purescript version of 'Real World App'](https://github.com/thomashoneyman/purescript-halogen-realworld)
- 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 Elmm when compared to PureScript](https://discourse.purescript.org/t/language-highlights/1471)

For those that say "PureScript is dead, bad, stupid, not worth learning, etc." In response to these things, I'd recommend you watch [The Hard Parts of Open Source](https://www.youtube.com/watch?v=o_4EX4dPppA)

Expand Down
4 changes: 2 additions & 2 deletions 00-Getting-Started/03-The-REPL.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ Type -> Type
### Show

There are two commands in this one:
- `show loaded`/`:s loaded` - Shows all modules which you can import into the REPL.
- `show import`/`:s imported` - Shows which modules you currently have imported in the REPL
- `show loaded`/`:s loaded` - Shows all modules that the REPL session knows about. Some may or may not have been imported. (Before the REPL session starts, the PureScript compiler will compile all PureScript files based on the source globs given to it. All modules in those globs are then known to the REPL session, but you might not want to use them all in a given session.)
- `show import`/`:s import` - Shows which modules you currently have imported into the REPL session

### Print

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,28 @@ infix 4 type TypeAlias as :$>
allPossibleCharactersForSymbolicAlias :: forall a. a -> a
allPossibleCharactersForSymbolicAlias x = x

-- Note: '@' and '\' cannot be used alone (see next comment)
infix 4 allPossibleCharactersForSymbolicAlias as ~\!@#$%^&*/><=+
-- Note: '@', '\', and '.' cannot be used alone (see next comment)
infix 4 allPossibleCharactersForSymbolicAlias as ~\!@#$%^&*/><=+.

{-
These characters, when used individuall as aliases, are illegal:
These characters, when used individually as aliases, are illegal:
infix 4 illegalAlias1 as \
^ That's reserved for lambdas
infix 4 illegalAlias2 as @
^ That's reserved for pattern matching: a@(Foo 1)
infix 4 illegalAlias3 as .
^ That's reserved for record-related things: foo.bar
-}
-- When used with more characters than themselves, they're fine and compile.
whenMultipleExist_itsFine :: forall a. a -> a
whenMultipleExist_itsFine x = x

infix 4 whenMultipleExist_itsFine as \\
infix 4 whenMultipleExist_itsFine as @@
infix 4 whenMultipleExist_itsFine as ..
infix 4 whenMultipleExist_itsFine as \.
infix 4 whenMultipleExist_itsFine as .@

-- Infix is all about where to put the parenthesis as indicated by precedence:
-- precedence is 0 = group first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ foreign import data YesK :: YesNoKind
foreign import data NoK :: YesNoKind

{-
Read yesK and yesK as:
Read yesK and noK as:
yesK = (YesNoProxyValue :: YesNoProxy Yes) - a value of type "YesNoProxy Yes"
noK = (YesNoProxyValue :: YesNoProxy No) - a value of type "YesNoProxy No" -}
yesK :: Proxy YesK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ foreign import data NoK :: YesNoKind
data YesNoProxy (a :: YesNoKind) = YesNoProxyValue

{-
Read yesK and yesK as:
Read yesK and noK as:
yesK = (YesNoProxyValue :: YesNoProxy Yes) - a value of type "YesNoProxy Yes"
noK = (YesNoProxyValue :: YesNoProxy No) - a value of type "YesNoProxy No" -}
yesK :: YesNoProxy YesK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import Effect (Effect)
import Effect.Console (log) -- log :: Effect Unit

-- | Describes but does not run a computation until RTS "calls unsafePerformEffect".
-- | Because the type signature of the last line's function`, `log`, is
-- | `Effect Unit`, it can be used as a main entry point into a program.
-- | The type signature of `log` is `String -> Effect Unit`. Thus, by applying
-- | a value of type `String` as an argument to `log`,
-- | `log "Hello World!"` has the type signature `Effect Unit`.
-- | Thus, it can be used as a main entry point into a program.
main :: Effect Unit
main = log "Hello world!"
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ Now might be a good time to re-read these articles:

## Evaluating MTL and Free

Alexis King recently recorded a very clear explanation of some of the tradeoffs of effect systems. While her video is in Haskell, the implications are worth thinking about in PureScript:
- [Alexis King - “Effects for Less” @ ZuriHac 2020](https://www.youtube.com/watch?v=0jI-AlWEwYI)

Let's now use the above post's criteria for each approach. The following is my guess at where things stand^^:

| | Extensible? | Composable? | Efficient? | Terse? | Inferrable?
Expand Down
3 changes: 2 additions & 1 deletion 22-Projects/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Note: each 'project' folder in the `src` folder has a corresponding folder in th
## Other "Example Projects"

- [hdgarrood's 'MultiPac' project](https://github.com/hdgarrood/multipac)
- [thomashoneyman's 'Real World App' project](https://github.com/thomashoneyman/purescript-halogen-realworld)
- [thomashoneyman's 'Real World App' (Halogen version)](https://github.com/thomashoneyman/purescript-halogen-realworld)
- [jonasbuntinx' - 'Real World App' (React Version)](https://github.com/jonasbuntinx/purescript-react-realworld)
- [jaspervdj's 'Beeraffe' game](https://github.com/jaspervdj/beeraffe/)
- [AndrewBrownK's 'Minesweeper CLI' game](https://github.com/AndrewBrownK/purescript-minesweeper-cli)

Expand Down
26 changes: 26 additions & 0 deletions 31-Design-Patterns/09-Generics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generics

Have you ever written boilerplate when implementing an instance for a type class (e.g. `Show`) and thought, "Surely, there must be a better/faster way!" Generics is the answer to your problems.

Here's the basic idea behind Generics:
1. You, the end developer, define a data type in your application and use the compiler to derive a `Generic` type class instance.
1. A library developer defines a function that can implement an instance for a given type class (e.g. `Show`, `BoundedEnum`, etc.) for all possible types.
1. You use the library developer's function to implement your data type's instance for a type class.

Great! So how does it work?

The compiler can define two functions, `to` and `from`. `to` converts your data type (i.e. `MyType`) to a new data type (let's say `CompilerRepresentationType` for lack of a better name) that has a different structure than your data type but stores the same information. `from` converts a value of `CompilerRepresentationType` back into a value of `MyType`.
These two functions abide by one law: `(from (to myDataTypeValue)) == myDataTypeValue`

The library developer writes a function that can implement an instance for the desired type class (e.g. `Show`, `BoundedEnum`) that works on `CompilerRepresentationType`. Generics works by first converting your data type into `CompilerRepresentationType`, then uses the library developer's function to implement the instance, and then converts the resulting value of the `CompilerRepresentationType` type back into your original type (i.e. `MyType`).

Put visually, read things from left to right as a timeline of events:
```
MyType --> CompilerRepresentationType ==> CompilerRepresentationType ~~> MyType
```
where
`-->` is where the compiler converts your type into the "same-info, different structure" type via the derived `to` function from the `Generic` type class
`==>` is the library developer's function that implements the instance
`~~>` is where the compiler converts the "same-info, different structure" type back into your type via the derived `from` function from the `Generic` type class

To understand how the compiler produces `CompilerRepresentationType` and how the library developer writes their function, read [@hdgarrood's "Making full use of PureScript's Generic type class"](https://harry.garrood.me/blog/write-your-own-generics/)
2 changes: 2 additions & 0 deletions 31-Design-Patterns/13-Recursion-Schemes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Recursion Schemes

See [Edward Kmett's "Recursion Schemes: A Field Guide"](http://comonad.com/reader/2009/recursion-schemes/) for a more-readable definition of the "xxx-morphism" terminology (e.g. hylomorphism).

See [Introduction to Recursion Schemes](https://blog.sumtypeofway.com/an-introduction-to-recursion-schemes/), a 4-part series that very clearly explains how they work and what they are. Papers referenced are below:
- [Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire](https://research.utwente.nl/en/publications/functional-programming-with-bananas-lenses-envelopes-and-barbed-w)
- [Primitive (Co)Recursion and Course-of-Value(Co)Iteration, Categorically](http://cs.ioc.ee/~tarmo/papers/inf99.pdf)
Expand Down

0 comments on commit 810c315

Please sign in to comment.