Skip to content

Why not use object #38

@2A5F

Description

@2A5F
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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions