Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove no part checked. Fixes #303. #311

Closed
wants to merge 8 commits into from
48 changes: 23 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,19 @@ Identity type, for example, could provide `Id` as its type representative:
If a type provides a type representative, each member of the type must have
a `constructor` property which is a reference to the type representative.


## `forAll`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might “Parametricity” be a better heading?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. If someone doesn't understand this signature because of the forall clause:

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

and tries to figure out what it is, a header that matches the confusing keyword is better than a term that -- given this confusion -- is likely unknown to them also.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Shall we use forall rather than forAll, though?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely. I'll fix that tonight.


[Parametric polymorphism][pp] is essential to these algebras. When the rules
for any type are specified as applied to all values (`forall a b`) of the
given generic types (here `a` and `b`), the rule must hold for any JavaScript
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering how can we make restrictions polymorphism implies more clear here.
What you think on something like this:(bold is for highlighting the addition):

Parametric polymorphism is essential to these algebras. When the rules
for any type are specified as applied to all values (forall a b) of the
given generic types (here a and b), the rule must hold for any possible
JavaScript value unless otherwise specified.
Since a parametrically polymorphic value does not "know" anything about the
type variables, it must behave the same regardless of its type. This is a somewhat
limiting but extremely useful property known as parametricity.
This implies, that a function should behave in same way for all values,
i.e. inspection of value is not allowed.
for instance, that code that
behaves differently for the null or undefined value than for other
values is unlikely to comply complying with the rule.

we can steal some ideas from https://wiki.haskell.org/Polymorphism or/and link to it too (has better explanation then wikipedia)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to expand this section. These are good ideas. The "unless otherwise specified" has to do with things like f must be a binary function or b must be same Apply as a. In such cases, not every value is allowable.

"is unlikely to comply" was about examples such as return r === null ? Maybe.of(r) : Maybe.of(r). The only way these examples could work is if their differences are not observable, so perhaps we can skip it. But it was part of the motivation for this change.

values unless otherwise specified. This implies, for instance, that code that
behaves differently for the `null` or `undefined` value than for other values
is unlikely to comply with the rule.

[pp]: https://en.wikipedia.org/wiki/Parametricity


## Algebras

### Setoid
Expand Down Expand Up @@ -363,7 +376,7 @@ method takes one argument:
#### `map` method

```hs
map :: Functor f => f a ~> (a -> b) -> f b
map :: forall a b. Functor f => f a ~> (a -> b) -> f b
```

A value which has a Functor must provide a `map` method. The `map`
Expand All @@ -376,7 +389,6 @@ method takes one argument:
1. If `f` is not a function, the behaviour of `map` is
unspecified.
2. `f` can return any value.
3. No parts of `f`'s return value should be checked.

2. `map` must return a value of the same Functor

Expand All @@ -389,7 +401,7 @@ method takes one argument:
#### `contramap` method

```hs
contramap :: Contravariant f => f a ~> (b -> a) -> f b
contramap :: forall a b. Contravariant f => f a ~> (b -> a) -> f b
```

A value which has a Contravariant must provide a `contramap` method. The
Expand All @@ -402,7 +414,6 @@ A value which has a Contravariant must provide a `contramap` method. The
1. If `f` is not a function, the behaviour of `contramap` is
unspecified.
2. `f` can return any value.
3. No parts of `f`'s return value should be checked.

2. `contramap` must return a value of the same Contravariant

Expand All @@ -416,7 +427,7 @@ implement the [Functor](#functor) specification.
#### `ap` method

```hs
ap :: Apply f => f a ~> f (a -> b) -> f b
ap :: forall a b. Apply f => f a ~> f (a -> b) -> f b
```

A value which has an Apply must provide an `ap` method. The `ap`
Expand All @@ -435,8 +446,6 @@ method takes one argument:
3. `ap` must apply the function in Apply `b` to the value in
Apply `a`

1. No parts of return value of that function should be checked.

4. The `Apply` returned by `ap` must be the same as `a` and `b`

### Applicative
Expand All @@ -451,7 +460,7 @@ implement the [Apply](#apply) specification.
#### `of` method

```hs
of :: Applicative f => a -> f a
of :: forall a. Applicative f => a -> f a
```

A value which has an Applicative must provide an `of` function on its
Expand All @@ -467,8 +476,6 @@ Given a value `f`, one can access its type representative via the

1. `of` must provide a value of the same Applicative

1. No parts of `a` should be checked

### Alt

A value that implements the Alt specification must also implement
Expand All @@ -480,7 +487,7 @@ the [Functor](#functor) specification.
#### `alt` method

```hs
alt :: Alt f => f a ~> f a -> f a
alt :: forall a. Alt f => f a ~> f a -> f a
```

A value which has a Alt must provide a `alt` method. The
Expand All @@ -493,7 +500,7 @@ A value which has a Alt must provide a `alt` method. The
1. If `b` is not the same Alt, behaviour of `alt` is
unspecified.
2. `a` and `b` can contain any value of same type.
3. No parts of `a`'s and `b`'s containing value should be checked.


2. `alt` must return a value of the same Alt.

Expand Down Expand Up @@ -539,7 +546,7 @@ the [Applicative](#applicative) and [Plus](#plus) specifications.
#### `reduce` method

```hs
reduce :: Foldable f => f a ~> ((b, a) -> b, b) -> b
reduce :: forall a b. Foldable f => f a ~> ((b, a) -> b, b) -> b
```

A value which has a Foldable must provide a `reduce` method. The `reduce`
Expand All @@ -552,11 +559,7 @@ method takes two arguments:
1. if `f` is not a function, the behaviour of `reduce` is unspecified.
2. The first argument to `f` must be the same type as `x`.
3. `f` must return a value of the same type as `x`.
4. No parts of `f`'s return value should be checked.

1. `x` is the initial accumulator value for the reduction
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why remove this line?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no problem putting it back. I just didn't see it adding anything. Is there something that makes it clear that an "empty" foldable will return this value? Do you think that this text captures that?


1. No parts of `x` should be checked.

### Traversable

Expand Down Expand Up @@ -691,7 +694,7 @@ A value that implements the Extend specification must also implement the [Functo
#### `extend` method

```hs
extend :: Extend w => w a ~> (w a -> b) -> w b
extend :: forall a b. Extend w => w a ~> (w a -> b) -> w b
```

An Extend must provide an `extend` method. The `extend`
Expand All @@ -704,7 +707,6 @@ method takes one argument:
1. If `f` is not a function, the behaviour of `extend` is
unspecified.
2. `f` must return a value of type `v`, for some variable `v` contained in `w`.
3. No parts of `f`'s return value should be checked.

2. `extend` must return a value of the same Extend.

Expand Down Expand Up @@ -740,7 +742,7 @@ the [Functor](#functor) specification.
#### `bimap` method

```hs
bimap :: Bifunctor f => f a c ~> (a -> b, c -> d) -> f b d
bimap :: forall a b c d. Bifunctor f => f a c ~> (a -> b, c -> d) -> f b d
```

A value which has a Bifunctor must provide a `bimap` method. The `bimap`
Expand All @@ -752,13 +754,11 @@ method takes two arguments:

1. If `f` is not a function, the behaviour of `bimap` is unspecified.
2. `f` can return any value.
3. No parts of `f`'s return value should be checked.

2. `g` must be a function which returns a value

1. If `g` is not a function, the behaviour of `bimap` is unspecified.
2. `g` can return any value.
3. No parts of `g`'s return value should be checked.

3. `bimap` must return a value of the same Bifunctor.

Expand All @@ -773,7 +773,7 @@ the [Functor](#functor) specification.
#### `promap` method

```hs
promap :: Profunctor p => p b c ~> (a -> b, c -> d) -> p a d
promap :: forall a b c d. Profunctor p => p b c ~> (a -> b, c -> d) -> p a d
```

A value which has a Profunctor must provide a `promap` method.
Expand All @@ -786,13 +786,11 @@ The `promap` method takes two arguments:

1. If `f` is not a function, the behaviour of `promap` is unspecified.
2. `f` can return any value.
3. No parts of `f`'s return value should be checked.

2. `g` must be a function which returns a value

1. If `g` is not a function, the behaviour of `promap` is unspecified.
2. `g` can return any value.
3. No parts of `g`'s return value should be checked.

3. `promap` must return a value of the same Profunctor

Expand Down