sanctuary-def dependency

Created on 22 Jan 2017  路  8Comments  路  Source: sanctuary-js/sanctuary

Sanctuary depends on sanctuary-def, as specified in __package.json__. Furthermore, Sanctuary is only compatible with certain versions of sanctuary-def. @codedmart recently brought it to my attention on Gitter that the example for create does not work if one uses the current version of Sanctuary (v0.11.1) with the current version of sanctuary-def (v0.9.0).

There are (at least) two things we should consider:

Most helpful comment

Here's what I think we should do:

  1. Separate all of sanctuary into small modules, each with a peer dependency on sanctuary-def (and possibly sanctuary-type-identifiers and other shared dependencies):

    • sanctuary-either to contain the Either type, its Repr, and associated functions

    • sanctuary-maybe to contain the Maybe type, its Repr, and associated functions

    • sanctuary-list for list related functions

    • sanctuary-string for string related functions

    • sanctuary-strmap for the StrMap type, its Repr, and related functions

    • ...more

  2. Create a sanctuary-prelude library which takes from each of the above libs to provide a set of common tools.
  3. The sanctuary library will have a single function. To load sanctuary-prelude and the shared peer dependencies like sanctuary-def, and instantiate the prelude with a default def.

People who want an out-of-the-box experience will use sanctuary, people who want a customized one will use sanctuary-prelude, people who want only parts of the functionality will assemble their own utility belt from the available underlying libs.

This tackles several problems:

  1. "The library is monolithic": Now we can choose what we want to include. Maybe in the future, each lib can even slit up into stuff like sanctuary-maybe-type, sanctuary-maybe-from-nullable. This package structure is "composable" all the way down to sanctuary.
  2. _(And this is personal:)_ "My colleagues are using require('sanctuary') directly, which defeats the point of disabling type-checking": Now, I will depend only on sanctuary-prelude, and provide my own assembly which they have to use.
  3. "My sanctuary-def is not compatible with yours": Since all packages but sanctuary have it as a peer dependency, they will all use the same version and NPM will show it when one is not compatible and should be down or upgraded.
  4. "I want to use my ENV_X to determine whether to check types": The community is now free to provide many Sanctuary assemblies, since it's very easy to set up. Just depend on the compatible sanctuary-* packages and export create(myDef).

All 8 comments

Could we use peerDependencies to express the constraint?

  "dependencies": {
    "sanctuary-def": "0.9.0",
    "sanctuary-type-classes": "2.0.1",
    "sanctuary-type-identifiers": "1.0.0"
  },
  "peerDependencies": {
    "sanctuary-def": "0.9.0"
  }

versioning the two packages such that [email protected] always depends on and works with [email protected]

This could be a handy indicator, but might also be a hassle to maintain and assure.

Could we use peerDependencies to express the constraint?

I've never seen peerDependencies used like that, though I haven't come across the situation where a package is both a dependency and a plugin to another package. I guess it might win us an automatic warning when the user tries to use an incompatible def, but I think it's all a bit messy. It relates the concerns I expressed here.

The problem, I think, is that multiple parties are creating black-box data structures (type definitions) using sanctuary-def and multiple parties need to interpret (call def on) those structures using sanctuary-def. Maybe it's possible for the future to ship the interpreter with "batteries included", eg:

const sanctuary = require('sanctuary');
const $ = require('sanctuary-def');
const env = $.env.concat(sanctuary.env).concat(myEnv);
const def = TYPE_CHECKING ? $.createTypecheckedDef(env) : $.def;

const S = sanctuary.create(def);

sanctuary would have to have a Peer Dependency on sanctuary-def, but not direct dependency. It's compatibility with def would only change if the type signature of def() changes, but not when the internal data structures change. Maybe It's a bad idea. Might be one for Ideas about env ;)

Ah I just realized what the flaw in my idea above is: In order to provide an env, we would still need sanctuary-def, and we'd still have the "multiple parties with incompatible data-structures"-problem.

But it does seem to me like removing sanctuary-def from dependencies and keeping it as only a peer-dependency would reduce complexity. If all these parties would do the same thing, you can be sure that the data structures will be compatible.

But it does seem to me like removing sanctuary-def from dependencies and keeping it as only a peer-dependency would reduce complexity.

I agree. const S = sanctuary.create(def); seems very nice to me! Let's seriously consider this change once we get v0.12.0 out the door. :)

Here's what I think we should do:

  1. Separate all of sanctuary into small modules, each with a peer dependency on sanctuary-def (and possibly sanctuary-type-identifiers and other shared dependencies):

    • sanctuary-either to contain the Either type, its Repr, and associated functions

    • sanctuary-maybe to contain the Maybe type, its Repr, and associated functions

    • sanctuary-list for list related functions

    • sanctuary-string for string related functions

    • sanctuary-strmap for the StrMap type, its Repr, and related functions

    • ...more

  2. Create a sanctuary-prelude library which takes from each of the above libs to provide a set of common tools.
  3. The sanctuary library will have a single function. To load sanctuary-prelude and the shared peer dependencies like sanctuary-def, and instantiate the prelude with a default def.

People who want an out-of-the-box experience will use sanctuary, people who want a customized one will use sanctuary-prelude, people who want only parts of the functionality will assemble their own utility belt from the available underlying libs.

This tackles several problems:

  1. "The library is monolithic": Now we can choose what we want to include. Maybe in the future, each lib can even slit up into stuff like sanctuary-maybe-type, sanctuary-maybe-from-nullable. This package structure is "composable" all the way down to sanctuary.
  2. _(And this is personal:)_ "My colleagues are using require('sanctuary') directly, which defeats the point of disabling type-checking": Now, I will depend only on sanctuary-prelude, and provide my own assembly which they have to use.
  3. "My sanctuary-def is not compatible with yours": Since all packages but sanctuary have it as a peer dependency, they will all use the same version and NPM will show it when one is not compatible and should be down or upgraded.
  4. "I want to use my ENV_X to determine whether to check types": The community is now free to provide many Sanctuary assemblies, since it's very easy to set up. Just depend on the compatible sanctuary-* packages and export create(myDef).

Is it UnaryType that breaks things currently?

I really don't know the internals of sanctuary so I have no idea what is possible but I assume that each of those packages would need sanctuary-def (78 kb) and sanctuary-type-classes (45kb). Right now sanctuary is 100kb, let's say sanctuary-maybe would me 15kb. Would it make sense to have a separate package of 15kb with 123kb of dependencies? In that case, me as a user, I would prefer to download an es6 modularized sanctuary and tree shake it myself. Other option is to ask if you are downloading a single package probably you are working on a small project and you would not need type checking, so remove type checking on individual packages -if possible.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

svozza picture svozza  路  8Comments

davidchambers picture davidchambers  路  8Comments

andrei-cacio picture andrei-cacio  路  8Comments

blackxored picture blackxored  路  7Comments

yotamDvir picture yotamDvir  路  3Comments