-
-
Save FbN/65fda3f881420b36e041a0b9f0964aa6 to your computer and use it in GitHub Desktop.
Clojure Protocols Inspired last param type polimorfism
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const of = x => ({ '@@type': 'A', x }) | |
export const f1 = a => a.x | |
f1.arity = 1 | |
export const f2 = c => a => a.x + c | |
f2.arity = 2 | |
export const f3 = d => c => a => a.x + c + d | |
f3.arity = 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const of = y => ({ '@@type': 'B', y }) | |
export const f1 = b => b.y | |
f1.arity = 1 | |
export const f2 = c => b => c + b.y | |
f2.arity = 2 | |
export const f3 = d => c => b => d + c + b.y | |
f3.arity = 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as A from './A.js' | |
import * as B from './B.js' | |
import protocol from './protocol.js' | |
const _ = protocol({ A, B }) | |
export const of = a => b => ({ '@@type': 'C', a, b }) | |
export const concat = v => c => ({ a: _.f2(v)(c.a), b: _.f2(v)(c.b) }) | |
concat.arity = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as A from './A.js' | |
import * as B from './B.js' | |
import * as C from './C.js' | |
import protocol from './protocol.js' | |
const _ = protocol({ A, B, C }) | |
const a = A.of('.A2.') | |
const b = B.of('.B2.') | |
const a2 = { | |
...a, | |
x: '.A2.' | |
} | |
console.assert(_.f1(a) === A.f1(a)) | |
console.assert(_.f1(b) === B.f1(b)) | |
console.assert(_.f1(b) !== A.f1(b)) | |
console.assert(_.f2('x')(a) === A.f2('x')(a)) | |
console.assert(_.f2('y')(b) === B.f2('y')(b)) | |
console.assert(_.f2('y')(b) !== A.f2('y')(b)) | |
console.assert(_.f2('x')(a2) === A.f2('x')(a2)) | |
console.assert(_.f2('x')(a2) !== B.f2('x')(a2)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const err = m => { | |
throw new Error(m) | |
} | |
export default function protocol (mods) { | |
const fSet = Object.entries(mods).reduce( | |
(fSet, [tn, ns]) => ({ | |
...fSet, | |
...Object.entries(ns) | |
.filter(e => typeof e[1] === 'function' && e[1].arity) | |
.reduce( | |
(rSet, [fn, f]) => ({ | |
...rSet, | |
[fn]: | |
fSet[fn] && fSet[fn] !== f.arity | |
? err('arity') | |
: f.arity | |
}), | |
{} | |
) | |
}), | |
{} | |
) | |
const f = fn => { | |
!fSet[fn] && err('not implemented') | |
switch (fSet[fn]) { | |
case 1: | |
return v => mods[v['@@type']][fn](v) | |
case 2: | |
return v => v2 => mods[v2['@@type']][fn](v)(v2) | |
case 3: | |
return v => v2 => v3 => mods[v3['@@type']][fn](v)(v2)(v3) | |
case 4: | |
return v => v2 => v3 => v4 => | |
mods[v4['@@type']][fn](v)(v2)(v3)(v4) | |
case 5: | |
return v => v2 => v3 => v4 => v5 => | |
mods[v5['@@type']][fn](v)(v2)(v3)(v4)(v5) | |
case 6: | |
return v => v2 => v3 => v4 => v5 => v6 => | |
mods[v6['@@type']][fn](v)(v2)(v3)(v4)(v5)(v6) | |
} | |
} | |
return Object.keys(fSet).reduce( | |
(out, fn) => ({ | |
...out, | |
[fn]: f(fn) | |
}), | |
{} | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment