-
-
Notifications
You must be signed in to change notification settings - Fork 24
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
(Optionally) automated environment via namespaces #137
Comments
How about // file1.js
// string -> StrMap Type -> ???
export default $.environment(({def, $, SumType}) => ({
TypeA: $.NullaryType(...),
TypeB: $.UnaryType(...),
TypeC: $.RecordType(...),
fn1: def(....),
fn2: def(....),
TypeD: SumType(...)
}));
// file2.js
// string -> Array ( Any -> Any ) -> ???
export default $.environment(({$}) => ({
TypeA: $.NullaryType(...),
TypeB: $.UnaryType(...),
TypeC: $.RecordType(...),
}));
// main.js
import env1 from 'file1';
import env2 from 'file2';
const makeNs = $.namespace({
def: S.create,
$: $.create,
SumType: SumType.create
});
const ns = makeNs('main', S.concat(env1, env2)); // env2 overwrites bindings from env1
const { bindings: {TypeA} } = ns;
const { TypeA: f1TypeA } = makeNs('', env1);
|
I like that revision! Maybe
That would automatically prefix any documentation urls in that namespace with that base url, and any type with that package prefix. |
Maybe $.namespace could be: namespace :: Boolean -> StrMap Function -> String -> String -> Environment The first argument is |
I don't like the idea of
This is the heart of the matter, I think. I believe there is an approach which avoids the ordering problem:
Here's a concrete example: // app/index.js
const {S, def} = require('./env');
... // app/env.js
const S = require('sanctuary');
const $ = require('sanctuary-def');
const CountryCode = require('./types/CountryCode');
const User = require('./types/User');
const UserId = require('./types/UserId');
// checkTypes :: Boolean
const checkTypes = true;
// env :: Array Type
const env = S.env.concat([CountryCode, User, UserId]);
exports.def = $.create({checkTypes, env});
exports.S = S.create({checkTypes, env}); // app/types/CountryCode.js
const $ = require('sanctuary-def');
module.exports = $.NullaryType(...); // app/types/User.js
const $ = require('sanctuary-def');
const UserId = require('./UserId');
module.exports = $.RecordType({
id: UserId,
firstName: $.String,
lastName: $.String,
}); // app/types/UserId.js
const $ = require('sanctuary-def');
module.exports = $.NullaryType(...); There are certainly ways in which we could make this more convenient, but the most important thing is to first establish the correct module layering:
If you agree with this layering, I'd love to know how well it works in your application, @JAForbes. |
@davidchambers Yeah I like this style, I saw you demonstrated it in the gitter after this discussion had taken place over there and I thought it was brilliant! I'm not sure if it works in the context of sum-type, we often want to define model types and page specific types in close proximity to the view because their helpful for modelling. And we will probably want to create functions using I think it would be a shame to need to move these page specific types to a separate file. The clean division your presenting is more difficult when we have hyper specific types for a particular page (model, enumerations of potential states and values specific to that page), not generic reusable types (like user, email, uuid etc). If you read Elm code you'll see this pattern often, hyper specific types to a particular component. It seems like our app specific sanctuary and sanctuary-def modules would be defined too early in this case. I don't have any solutions, just voicing a concern 😄 |
This helps me to understand your requirements. :) I suggest that you experiment in your application and comment again in this thread once you arrive at a satisfactory solution. |
Great idea
…-----Original Message-----
From: "David Chambers" <[email protected]>
Sent: 5/9/2017 3:00 PM
To: "sanctuary-js/sanctuary-def" <[email protected]>
Cc: "James Forbes" <[email protected]>; "Mention" <[email protected]>
Subject: Re: [sanctuary-js/sanctuary-def] (Optionally) automated environmentvia namespaces (#137)
If you read Elm code you'll see this pattern often, hyper specific types to a particular component.
This helps me to understand your requirements. :)
I suggest that you experiment in your application and comment again in this thread once you arrive at a satisfactory solution.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
I find myself calling
create
and passing around differentenv
's of types in many files, and I've only just started really leaning on sanctuary in a large project, and its going to get worse.I've thought about different ways to structure this to prevent the verbosity, but I thought I'd at least vent the radical thought that keeps coming to mind.
What I really want, is an automated env. I don't want to pass env's around, I want to define a type and ideally I want sanctuary-def to manage the concatenation for me.
This came up when I was working on sum-type, I wanted to be able to nest union types, and I wasn't sure if that meant I needed to insert the previously created types into the env of any new types. So to date (I think), that's exactly what I do. Its technically still pure, it just automatically gives each type a new env that includes the previously defined types. I don't know if I actually need to do that, but whether or not I do, it at least makes me wonder, why don't we do this by default?
I don't want to have to think about order of operations across possibly 100's of modules.
I want to be able to write
$.RecordType({ ... })
and know I can use that type anywhere now.Now there's problems, maybe we don't want some subset of a project to include the environment from another part of a project. I think this is solved in programming languages via a
namespace
.So what if we had
$.namespace
And then in one place, we can initialise that
namespace
.Just walking through the signatures,
$.createNamespace
would accept a namespace name, and a list of functions that receive{ checkTypes, env }
,sanctuary-def
would somehow initialize them for us, and manage concatenating the environment behind the scenes. This is very hand wavey! 😄I'm not sure what
$.createNamespace
would return, I have a few ideas. One option, it could return a merged object of whatever each$.namespace
returned, essentially giving us an analogue to modules. Another idea could be to return an interface that gives the caller control over exception handling (whether to throw, or write errors to a stream etc)This API could let us do cool things, like use different namespaces for testing, or hot paths. Or control execution of code that depends on sanctuary-def types. Now we can toggle env for the entire namespace (across files) in one place. We also don't need to concern ourselves with concatenating different type arrays, because namespaces would automatically do that for us.
It's very opinionated, and maybe would be better off as a library, but I don't know if it would be possible to do this in user-land.
Its a very broad debatable idea, but seems interesting to me. I'd love to hear some criticism!
The text was updated successfully, but these errors were encountered: