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

Add type signatures to spec #147

Merged
merged 1 commit into from Sep 5, 2016

Conversation

scott-christopher
Copy link
Contributor

Addresses #138

Throwing this up as a bit of a strawman, as there will no doubt be differing opinions around syntax.

I put forward the following suggestion:

sequence :: Apply f, Traversable t => t (f a) ~> (b -> f b) -> f (t a)
'------'    '--------------------'    '-----'    '-------------------'
   '- method name     '- constraints     '- method target  '- method arguments

I'm also not sure whether an explanation of the syntax should be included in the spec or not.

@SimonRichardson
Copy link
Member

👍

@rpominov
Copy link
Member

rpominov commented Aug 9, 2016

This looks great! Only one thing worries me, this type syntax was designed for curried functions, while our methods are not curried.

For instance:

 reduce :: Foldable f => f a ~> (b -> a -> b) -> b -> b

seems like a.reduce(fn) returns a function, and that fn should be curried.

@scott-christopher
Copy link
Contributor Author

Only one thing worries me, this type syntax was designed for curried functions, while our methods are not curried.

Good point. We could using tuples to represent arguments instead.

Foldable f => f a ~> (((b, a) -> b), b) -> b

It seems like it's a bit of a trade off in terms of readability.

Also, is there any preference for keeping or removing the method name from the signature?

@rpominov
Copy link
Member

rpominov commented Aug 9, 2016

+1 for tuples, this would be more correct.

@rpominov
Copy link
Member

rpominov commented Aug 9, 2016

Ah, maybe we could also remove descriptions like the following now?

The `equals` method takes one argument:

     a.equals(b)

 1. `b` must be a value of the same Setoid

     1. If `b` is not the same Setoid, behaviour of `equals` is
        unspecified (returning `false` is recommended).

 2. `equals` must return a boolean (`true` or `false`).

Since this is basically type signatures in english, and we now have proper type signatures.

@SimonRichardson
Copy link
Member

Can we keep both? I find that it lends to the appeal of the spec, as in, some people don't know how to read haskell and reading the description helps people understand that.

@davidchambers
Copy link
Member

I'm very much in favour of this proposal.

In Haskell the constraints are parenthesized when there are multiple constraints. I don't know whether there's a compelling reason for this or whether the decision was made to simplify the grammar.

@SimonRichardson
Copy link
Member

@joneshf you happy for me to merge this one?

@SimonRichardson SimonRichardson merged commit 31f28fb into fantasyland:master Sep 5, 2016
rjmk added a commit to rjmk/fantasy-land that referenced this pull request Sep 6, 2016
* 'master' of github.com:fantasyland/fantasy-land:
  Add ChainRec specification (fantasyland#152)
  Add type signatures to spec (fantasyland#147)
@@ -276,6 +304,10 @@ Compose.prototype.map = function(f) {

#### `sequence` method

```hs
sequence :: Apply f, Traversable t => t (f a) ~> (b -> f b) -> f (t a)
Copy link
Member

Choose a reason for hiding this comment

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

Should this be Applicative f rather than Apply f? c -> f c is of essentially, isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In practice yes, but I decided to just use the Apply constraint here because the of function (or any function that can lift a value into the Apply) has to be provided by the caller, so the constraint is then just that the type returned by the given function must be an Apply.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, so you're drawing a distinction between a type which could provide of and a type which actually provides it. My view is that every type which can provide of should do so, but I understand your position.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd be happy for it to change if it would help avoid confusion.

Copy link
Member

Choose a reason for hiding this comment

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

In Haskell b -> f b would be inferred from f rather than provided as an argument, so f would need to satisfy Applicative.

In JavaScript f doesn't need to satisfy Applicative, strictly speaking, though it must be capable of supporting Applicative.

Apply f => is technically correct; Applicative f => is more descriptive. The question is whether we should favour correctness or descriptiveness. Does anyone have a strong view on this?

Copy link
Member

@rpominov rpominov Sep 19, 2016

Choose a reason for hiding this comment

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

I can add a point that in laws we use Applicative (e.g. "for any Applicative F"), although maybe we should use Apply in laws :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants