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

Why not use object #38

Open
2A5F opened this issue Apr 29, 2021 · 0 comments
Open

Why not use object #38

2A5F opened this issue Apr 29, 2021 · 0 comments

Comments

@2A5F
Copy link

2A5F commented Apr 29, 2021

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;
    }
}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant