Skip to content

Commit

Permalink
Merge pull request #434 from JordanMartinez/development
Browse files Browse the repository at this point in the history
Make next minor release: ps-0.13.x-v0.23.1
  • Loading branch information
JordanMartinez committed Feb 20, 2020
2 parents f357f5e + 0fc2f39 commit 2770594
Show file tree
Hide file tree
Showing 14 changed files with 2,707 additions and 1,157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ Here's a "big picture" flowchart for what a person does and how it fits into the
- You cannot use this workflow to develop libraries. Use `pulp` and `bower` for that.
- Minor / has workarounds
- There is no built-in `browserify` command (like `pulp`). So, you need to execute that command (or `parcel`) yourself.
- Just like `bower`, you still need to use `npm` to install JavaScript libraries for any PureScript bindings. To understand why, see https://github.com/spacchetti/spago#why-cant-spago-also-install-my-npm-dependencies
- Just like `bower`, you still need to use `npm` to install JavaScript libraries for any PureScript bindings. To understand why, see https://github.com/purescript/spago#why-cant-spago-also-install-my-npm-dependencies
2 changes: 1 addition & 1 deletion 02-Build-Tools/02-Build-Tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Unfortunately, `purs-loader` (webpack for PureScript) still has out-of-date exam
- [psc-package example](https://github.com/ethul/purescript-webpack-example/tree/psc-package)
- [bower / fast rebuild example](https://github.com/ethul/purescript-webpack-example/tree/fast-rebuilds)

[`spago`](https://github.com/spacchetti/spago) is a more recent development that is picking up steam. It is designed to work well with [`parcel`](https://parceljs.org/)
[`spago`](https://github.com/purescript/spago) is a more recent development that is picking up steam. It is designed to work well with [`parcel`](https://parceljs.org/)
2 changes: 1 addition & 1 deletion 02-Build-Tools/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Spago dropped support for `psc-package` commands in the `v0.11.0` release. `psc-
| psvm-js | PureScript Version Manager | -- | https://github.com/ThomasCrevoisier/psvm-js
| bower | Dependency Manager | -- | https://bower.io/ |
| pulp | Build Tool | Front-end to `purs`. Builds & publishes projects | https://github.com/purescript-contrib/pulp |
| spago | Build Tool | Front-end to `purs` and `psc-package` projects | https://github.com/spacchetti/spago
| spago | Build Tool | Front-end to `purs` and `psc-package` projects | https://github.com/purescript/spago
| pscid | `pulp --watch build` on steroids | Seems to be a more recent version of `psc-pane` (see below) and uses `psa` | https://github.com/kRITZCREEK/pscid
| psa | Pretty, flexible error/warning frontend for `purs` | -- | https://github.com/natefaubion/purescript-psa

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Understanding Type Inference

The below video explains how type inference works. It can be very helpful to understand what is going on behind the scenes when you get compiler errors: [How GHC's Type Inference Engine Works](https://www.youtube.com/watch?v=x3evzO8O9e8)
1,059 changes: 1,059 additions & 0 deletions 21-Hello-World/04-Collections-and-Loops/assets/unfoldable-visualized.graphml

Large diffs are not rendered by default.

Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions 21-Hello-World/04-Collections-and-Loops/spago.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ You can edit this file as you like.
, "filterable"
, "foldable-traversable"
, "psci-support"
, "unfoldable"
]
, packages = ../../packages.dhall
, sources = [ "src/**/*.purs" ]
Expand Down
136 changes: 136 additions & 0 deletions 21-Hello-World/04-Collections-and-Loops/src/04-Unfoldable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Unfoldable

## Usage

Plain English names:
- Generator
- FP version of a generic "while" loop

```
Given
a function, `f`,
that uses the next `b` value to generate
either the case that ends the while loop, `Nothing`
or the case that continues the while loop, `Just`
which wraps a `Tuple` so that it can return
the first or next value, `a`, that gets "put into" the `t` container
and
the next `b` value that is then used by `f`
to run the next iteration in the loop
and
the first `b` value
return a container/collection, `t`, that stores all the `a` values
that were generated by the `f` function,
which may "contain" 0 or many `a` values.
```

It enables:
- a way to generate a `List` of `Ints`s where each `Int` in the `List` is one greater than the previous `Int`
- a way to run the same `Effect`/`Aff` computation multiple times until a given condition is true

## Definition

### Code Definition

Don't look at its docs until after looking at the visual overview in the next section: [Unfoldable](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable#t:Unfoldable)

```purescript
-- We'll ignore the `Unfoldable1` superclass for now..
class Unfoldable1 t <= Unfoldable t where
unfoldr :: forall a b. (b -> Maybe (Tuple a b)) -> b -> t a
```

### Visual Overview

![unfoldable-visaulized](../assets/unfoldable-visualized.svg "Unfoldable Visualized")


### Examples

We'll implement an instance for `List a`.

#### `List`'s Instance

```purescript
data List a = Nil | Cons a
instance unfoldableList :: Unfoldable List where
unfoldr :: forall a b. (b -> Maybe (Tuple a b)) -> b -> List a
unfoldr f initialB = case f initialB of
Nothing -> Nil
Just (Tuple a nextB) -> Cons a (unfoldr f nextB)
```

## Laws

None

## Derived Functions

### Overview of Possible Functions for `f`

The only part of `unfoldr f initialB` we can hard-code in a derived function is the `f` function. There are three different functions we could use for `f`:
```purescript
-- We'll use this type alias in the next couple of sections
type UnfoldrFunction a b = b -> Maybe Tuple a b
-- case 1
alwaysReturnJust :: forall a b. a -> b -> UnfoldrFunction a b
alwaysReturnJust a b = \initialB -> Just (Tuple a b)
-- case 2
alwaysReturnNothing :: forall a b. UnfoldrFunction a b
alwaysReturnNothing _ = Nothing
-- case 3
itDepends :: forall a b. UnfoldrFunction a b
itDepends = -- possibilities are shown later
```

| Case Name | Derived Function Name | Result |
| - | - | - |
| case 1 | !!! 😱😱😱 !!! | **Runtime Error: Infinite loop!** |
| case 2 | [`none`](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable#v:none) | Produces an empty `t` |
| case 3 | `replicate`, `replicateA`, and `fromMaybe` | see below overviews of each function

Case 1 functions always produce a runtime error due to creating an infinite loop. They will appear in two ways:
```purescript
-- obvious because Just is always returned
example1 = unfoldr (const Just (Tuple 0 0)) 0
-- Not as obvious in situations where
-- there are a lot of possible conditions
example2 =
unfoldr f 0
where
f nextB
| nextB < 0 = Just (Tuple 1 2)
| nextB > 0 = Just (Tuple 2 -4)
| nextB == 0 = Just (Tuple 8 4)
| otherwise = Nothing
-- ^ this case never occurs
```

### Case 3 Functions

#### Using a countdown or countup function to do something `n`-many times

```purescript
countUp :: forall a. Int -> UnfoldrFunction a Int
countUp limit = \nextInt ->
if nextInt >= limit then Nothing
else Just (Tuple aValue (nextInt + 1))
countDown :: forall a. UnfoldrFunction a Int
countDown = \nextInt ->
if nextInt <= 0 then Nothing
else Just (Tuple aValue (nextInt - 1))
```

These kinds of functions are used in the following derived functions:
- [`replicate`](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable#v:replicate) - Add the same `a` value to a `t` container `x` number of times.
- [`replicateA`](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable#v:replicate) - Run the same applicative-based computation `x` number of times and store their results in the `t` container.

#### Converting a `Maybe` into another type that has an `Unfoldable` instance

- [`fromMaybe`](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable#v:fromMaybe)
42 changes: 42 additions & 0 deletions 21-Hello-World/04-Collections-and-Loops/src/05-Unfoldable1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Unfoldable1

This is the same as `Unfoldable` except the returned `t` value must always have at least 1 `a` value. As a result, it's actually harder to find a data type that can **only** implement `Unfoldable1` but can't implement `Unfoldable`.

## Definition

### Code Definition

```purescript
class Unfoldable1 t where
unfoldr1 :: forall a b. (b -> Tuple a (Maybe b)) -> b -> t a
```

The only difference between `Unfoldable` and `Unfoldable1` is the type signature for `f`. In both cases, the `b` value is inside of a `Maybe`:
```purescript
-- Unfoldable
f :: forall a b. b -> Maybe (Tuple a b)
-- Unfoldable1
f :: forall a b. b -> Tuple a (Maybe b)
```

## Laws

None

## Derived Functions

### Parallels to `Unfoldable`

| Concept | Unfoldable<br>(`t` can be empty) | Unfoldable1<br>(`t` can't be empty) |
| - | - | - |
| Produce a `t` value | `none` | [`singleton`](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable1#v:singleton) |
| Add an `a` `n`-many times to a `t` container | `replicate` | [`replicate1`](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable1#v:replicate1) |
| Run an applicative-based computation `n`-many times and store the results in a `t` container | `replicateA` | [`replicate1A`](https://pursuit.purescript.org/packages/purescript-unfoldable/docs/Data.Unfoldable1#v:replicate1A) |
| Convert `Maybe a` to `t a` | `fromMaybe` | possible, but not implemented |

`Unfoldable1` does not have a version of `fromMaybe` included, but I believe it is possible if one places a `Monoid` constraint on `a` and uses `mempty` when receiving a `Nothing` case.

### Specific to `Unfoldable1`

- [`range`](https://pursuit.purescript.org/packages/purescript-unfoldable/4.1.0/docs/Data.Unfoldable1#v:range)
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ See [Motivation behind Phantom Types](https://stackoverflow.com/questions/282475
- See [Pathy](https://github.com/slamdata/purescript-pathy#introduction), which uses them to track the distinctions of relative/absolute file paths and of file/directory
- Use phantom types to estimate the state of "the real world" in a monadic computation:
- Search for an explanation of Indexed Monads
- Use phantom types to "save" proofs
- Watch [Ghosts of Departed Proofs](https://www.youtube.com/watch?v=2cAxOJEiL00) (not the best video quality, but very interesting ideas)
3 changes: 2 additions & 1 deletion 31-Design-Patterns/11-Optics.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ To learn how to use lenses...

Below are other resources that are more reference material than clear explanations to beginners:
- [Oleg's Glassery post](http://oleg.fi/gists/posts/2017-04-18-glassery.html)
- The [Racket Programming Languages's Lenses Guide](https://docs.racket-lang.org/lens/index.html).
- The [Racket Programming Languages's Lenses Guide](https://docs.racket-lang.org/lens/index.html).
- [Profunctor Optics, a Categorical Update (Extended Abstract)](https://cs.ttu.ee/events/nwpt2019/abstracts/paper14.pdf)

## Lenses

Expand Down
3 changes: 3 additions & 0 deletions 31-Design-Patterns/17-Church-Encoding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Church Encoding

See [Scrap Your Constructors: Church Encoding Algebraic Types](https://programmable.computer/posts/church_encoding.html)

0 comments on commit 2770594

Please sign in to comment.