Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const Protocol = ([name]) => (def) =>
- def.reduce((pro, curr) => {
- if (Array.isArray(curr)) {
- const [field, fn] = curr
- pro[field] = Symbol(`${name}.${field}`)
- pro[Protocol.methods].push({
- symbol: pro[field],
- fn,
- })
- pro[Protocol.symbols].push({
- name: curr,
- symbol: pro[curr],
- })
- }
- else {
- pro[curr] = Symbol(`${name}.${curr}`)
- pro[Protocol.symbols].push({
- name: curr,
- symbol: pro[curr],
- })
- }
- return pro
- }, { [Protocol.methods]: [], [Protocol.symbols]: [], [Protocol.origin]: name })
- Protocol.methods = Symbol('Protocol.methods')
- Protocol.symbols = Symbol('Protocol.symbols')
- Protocol.origin = Symbol('Protocol.origin')
- Protocol.implement = function(target, ...protocols) {
- protocols.forEach(protocol => {
- protocol[Protocol.methods].forEach(({ symbol, fn }) => {
- target.prototype[symbol] = fn
- })
- protocol[Protocol.symbols].forEach(({ name, symbol }) => {
- if (!(target[symbol] || target.prototype[symbol])) {
- const tn = target.constructor && target.constructor.name || target
- throw new TypeError(
- `${tn} not correctly implements ${protocol[Protocol.origin]}.\n`
- + `${name} not found as ${symbol.toString()}`
- )
- }
- })
- })
- }
- const Functor = Protocol`Functor`([
- 'map',
- ])
- const map = fn => target => {
- if (target[Functor.map]) {
- return target[Functor.map](fn)
- }
- else if (target.map) {
- return target.map(fn)
- }
- throw new TypeError('Not have @@map')
- }
- Promise.prototype[Functor.map] = function(fn) {
- return this.then(value => fn.call(this, value))
- }
- Protocol.implement(Promise, Functor)
- map(console.log)(Promise.resolve(12))
- Array.prototype[Functor.map] = function(fn) {
- return this.map(fn)
- }
- Protocol.implement(Array, Functor)
Add Comment
Please, Sign In to add comment