-
Notifications
You must be signed in to change notification settings - Fork 9
Open
Description
protocol ToString {
tag;
toString() {
return `[object ${this[ToString].tag}]`;
}
}
Protocol.implement(Object, ToString);
Object.prototype[ToString] = { tag: 'Object' };
// or
Object.prototype[ToString].tag = 'Object';
in #34 syntax
implement ToString for Object {
tag = 'Object'
}
protocol Functor {
map;
}
implement Functor for Promise {
map(f) {
return m => m.then(f);
}
}
function map(m, f) {
return m[Functor].map(f)(m);
}
in ts
protocol Functor<F extends for<_>> {
map<T, R>(f: (v: T) => R): F<T> => F<R>;
}
implement Functor<Promise> for Promise {
map<T, R>(f: (v: T) => R): Promise<T> => Promise<R> {
return m => m.then(f);
}
}
function map<M extends for<_> { [Functor]: Functor<M> }, T, R>(m: M<T>, f: (v: T) => R): M<R> {
return m[Functor].map(f)(m);
}
Another proposal
protocol <name> [extends <protocol_extends>] {
<slots>;
<fields> = <expr>;
<methods>() { };
}
implement <protocol> for <constructor> [as <impl_alias>] [extends <impl_extends>] { <object body> }
implement <protocol> of <object> [as <impl_alias>] [extends <impl_extends>] { <object body> }
implement <protocol> [as <impl_alias>] [extends <impl_extends>] { <object body> }
<value> instanceof <protocol>
<name>
is symbol
1. SomeObject = {
prototype: { },
}
2. call Protocol.implement(SomeProtocol, [SomeObject.prototype]);
3. SomeObject = {
prototype: {
[SomeProtocol]: {
<slots>: undefined, // has key but value is undefined
<fields> = 1,
__proto__: {
<methods>() { },
}
}
},
}
4. SomeObject[SomeProtocol].<slots> = 1
2.2 call Protocol.implement(SomeProtocol, [SomeObject.prototype], {
<slots>: 1,
<fields> = 2
});
2.3 call Protocol.implement(SomeProtocol, [Foo, Bar]); // impl for multi
2.4 call Protocol.implement(SomeProtocol, [Foo, Bar], { }); // impl for multi with object
polyfill
const ProtocolMap = new Map
Protocol.define = (name, def, opt) => {
const symbol = Symbol(name)
ProtocolMap.set(symbol, { def, opt })
return symbol
}
Protocol.implement = (protocol, objs, impl) => {
const { def, opt } = ProtocolMap.get(protocol)
let base = null;
if (opt != null && typeof opt === 'object' && 'extends' in opt && ProtocolMap.has(opt.extends)) {
const needsuper = objs.filter(o => !(protocol in o))
if (needsuper.length != 0) {
base = Protocol.implement(opt.extends, needsuper, impl)
}
}
const proto = Object.fromEntries(Object.entries(def).filter(([k, v]) => typeof v === 'function'))
const insta = Object.fromEntries(Object.entries(def).filter(([k, v]) => typeof v !== 'function'))
const obj = Object.assign(Object.assign(Object.create(Object.assign(Object.create(base), proto)), insta), impl)
for (o of objs) {
o[protocol] = obj
}
return obj
}
Protocol.instanceof = (obj, protocol) => protocol in o
// define
protocol Functor {
map;
}
var Functor = Protocol.define('Functor ', {
map: void 0;
})
// impl
implement Functor for Promise {
map(f) {
return m => m.then(f);
}
}
Protocol.implement(Functor, [Promise.prototype], {
map(f) {
return m => m.then(f);
}
})
// impl for object
implement Functor of Promise.prototype {
map(f) {
return m => m.then(f);
}
}
// impl for nothing
implement Functor as NullableFunctor {
map(f) {
return m => m == null ? null : f(m);
}
}
var NullableFunctor = Protocol.implement(Functor, [], {
map(f) {
return m => m == null ? null : f(m);
}
})
// protocol extends
protocol Monad extends Functor {
bind;
return;
}
implement Monad for Promise {
bind(f) {
return m => m.then(f);
},
return(v) {
return Promise.resolve(v);
}
}
var Monad = Protocol.define('Monad ', {
bind: void 0;
return: void0;
}, { extends: Functor })
Protocol.implement(Monad, [Promise.prototype], {
bind(f) {
return m => m.then(f);
},
return(v) {
return Promise.resolve(v);
}
})
// impl extends
implement Monad as NullableMonad extends NullableFunctor {
bind(f) {
return m => m == null ? null : f(m);
},
return(v) {
return v;
}
}
var NullableMonad = Protocol.implement(Monad, [], Object.assign(Object.create(NullableFunctor), {
bind(f) {
return m => m == null ? null : f(m);
},
return(v) {
return v;
}
}))
Metadata
Metadata
Assignees
Labels
No labels