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

Use a thunk instead of a direct reference to the canonical module #2

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ All methods' implementations should only use type information about arguments th

## Canonical Module

A value may have a reference to a canonical module that works with values of that value's type. The reference should be in the `fantasy-land/canonical` property. For example:
A value may have a reference to a canonical module that works with values of that value's type. Such a value should have a method named `fantasy-land/canonical` that returns the module. For example:

```js
const ListModule = {
of(x) {
return {'fantasy-land/canonical': ListModule, data: [x]}
return {'fantasy-land/canonical': () => ListModule, data: [x]}
},
map(f, v) {
return {'fantasy-land/canonical': ListModule, data: v.data.map(f)}
return {'fantasy-land/canonical': () => ListModule, data: v.data.map(f)}

Choose a reason for hiding this comment

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

I think f and v will not be gc-ed as fantasy-land/canonical has reference to it

Copy link
Owner Author

Choose a reason for hiding this comment

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

As far as I know, compilers can notice that these variables are not used in the function so they won't count this as references during garbage collection. But I'm not an expert.

Also in real code I wouldn't create the function on a spot like this, but would create it once and then reuse. Not sure though if we should do this in the example and complicate it.

}
}
```
Expand All @@ -115,11 +115,13 @@ const ListModule2 = {
}
}

const list = {'fantasy-land/canonical': ListModule2, data: [1]}
const list = {'fantasy-land/canonical': () => ListModule2, data: [1]}
```

Note that the `ListModule2` here is correct. Only the `list` value doesn't follow the specification.

The `fantasy-land/canonical` method must always return equivalent modules when called multiple times.

Choose a reason for hiding this comment

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

I don't quite understand what's the point of fantasy-land/canonical being a function. like if we ask it always return equivalent modules when called multiple times, i.e. being pure, then it's only advantage I see is being able to lazily contract the value, which i don't see as significant optimization, I also haven't read that conversation so all this might be discussed in that issue

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think the discussion boils down to this sentence:

By not making it a thunk the API is imposing an evaluation strategy, which in JavaScript in particular is a pretty serious problem due to the order of evaluation. (c) @alexandru

I'm also not sure about the importance of such flexibility, but on the other hand seems like it won't hurt anyway.

Choose a reason for hiding this comment

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

@alexandru can you point out "practical" example where fantasy-land/canonical being lazy is more useful/better then it being non lazy?



## Algebra

Expand Down