question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ADTs defined using S functions are compatible only with types known to S

See original GitHub issue

In resolving conflicts between #216 and #232 I discovered a problem. Consider this example:

//# Identity#fantasy-land/traverse :: Applicative f => Identity a ~> (a -> f b, c -> f c) -> f (Identity b)
Identity.prototype['fantasy-land/traverse'] = function(f, of) {
  return S.map(Identity, f(this.value));
};

Seems fine, doesn’t it? Yes, but for the fact that by using S.map we’re limiting the types with which this method is compatible to the types known to S.

This is very much related to sanctuary-js/sanctuary-def#74.

As things stand, I see two workarounds:

  • use S.create({checkTypes: false, env: []}).map in place of S.map; or
  • provide a create :: { checkTypes :: Boolean, env :: Array Type } -> Module function which returns an Identity constructor compatible with the desired set of types.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
davidchamberscommented, Dec 18, 2017

Using sanctuary-type-classes is absolutely the right approach. ADT libraries are foundational so should not depend on high-level libraries such as Sanctuary. Sanctuary is large and has many dependencies.

+---------------------------------------------------------+
|                                                         |
|                       application                       |
|                                                         |
+---------------------------------------------------------+

+---------------------------------------------------------+
|                        sanctuary                        |
+---------------------------------------------------------+

+---------------+   +-----------------+   +---------------+
| sanctuary-map |   | sanctuary-maybe |   | sanctuary-set |
+---------------+   +-----------------+   +---------------+

+---------------------------------------------------------+
|                 sanctuary-type-classes                  |
+---------------------------------------------------------+

+---------------------------------------------------------+
|                                                         |
|                                                         |
|        JavaScript's built-in types and functions        |
|                                                         |
|                                                         |
+---------------------------------------------------------+
1reaction
davidchamberscommented, Jan 16, 2017

We decided the behaviour of require('sanctuary') should remain unchanged

It would, in my proposal. S.safe() would only exist to provide a customized environment (in the absence of mutation), and S is defined by S.safe(S.env).

Oh, I see. 😃

The only question that remains is whether to expose a more convenient way to access unsafe Sanctuary functions, eg. S.unsafe.map. I think that should be possible, since unsafe functions don’t need an env, nor to know whether to check types. Essentially we’re adding a second preconfigured Sanctuary, the first being S itself.

I do like the idea of reinstating S.unchecked—I prefer “unchecked” to “unsafe”—for ergonomics:

const S = require('sanctuary').unchecked;
const S = require('sanctuary').create({checkTypes: false, env: []});

Were we to do so, the checkTypes member of the { checkTypes :: Boolean, env :: Array Type } record would become redundant, as you noted. S.create would only be necessary for creating type-checked modules with custom environments, so we could change its type to Array Type -> Module. There are two minor drawbacks of this approach: S.create would no longer mirror $.create, and switching based on process.env.NODE_ENV or similar would be slightly messier.

I’m keen to reinstate S.unchecked if you think it’s a good idea. We may or may not decide to change S.create while we’re at it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Reading 12: Defining ADTs with Interfaces, Generics ...
Today's class is about various ways to implement abstract data types, including: interfaces: separating the interface of an ADT from its implementation; ...
Read more >
AbstractDataTypes
Abstract data types are data types whose implementation is not visible to their user; from the outside, all the user knows about an...
Read more >
[Solved] Using ADTs abstract data types has advantages ...
ADT's or abstract data types facilitate developers to use various functions just by importing the required library and using associated functions without ...
Read more >
Abstract Data Types
Abstract Data type (ADT) is a type (or class) for objects whose behavior is defined by a set of values and a set...
Read more >
Abstract Data Types in C
With procedural abstraction, we use functions based on their signature and documentation without having to know details about their definition.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found