Skip to content

Instantly share code, notes, and snippets.

@moosch
Last active July 16, 2019 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moosch/8ab9d9336d8efc07fa36f77e8afb4588 to your computer and use it in GitHub Desktop.
Save moosch/8ab9d9336d8efc07fa36f77e8afb4588 to your computer and use it in GitHub Desktop.
/**
* Semigroup
*
* A Semigroup must have a concat method.
* Just like JS Array and String
*
* It simply takes 2 of the same datatype, concats them and returns that same datatype
*
* The type signature for the concat method:
* concat :: Semigroup a => a ~> a -> a
*
* Spec: https://github.com/fantasyland/fantasy-land#semigroup
*/
const getDataType = (a) => {
if (a === undefined) {
return 'Undefined';
}
if (a === null) {
return 'Null';
}
return (a).name || ((a).constructor && (a).constructor.name);
}
const typeGuard = (a, b) => {
const aType = getDataType(a);
const bType = getDataType(b);
if (aType !== bType) {
throw new TypeError(`Type mismatch. Expected ${aType} datatype`);
}
}
const typeSafeConcat = (a, b) => {
const type = getDataType(a);
switch (type) {
case 'Number':
case 'BigInt':
default:
return a + b;
case 'String':
case 'Array':
return a.concat(b);
case 'Object':
return { ...a, ...b };
case 'Boolean':
return Boolean(a + b);
case 'Function':
throw TypeError('Cannot concat datatype Function');
case 'Symbol':
throw TypeError('Cannot concat datatype Symbol');
case 'Null':
return null;
case 'Undefined':
return undefined;
}
}
const Semigroup = (a) => ({
a,
toString: () => `Semigroup(${a})`,
concat: (b) => {
typeGuard(a, b);
return Semigroup(
typeSafeConcat(a, b),
);
},
});
Semigroup('Hello,').concat(' World!'); // => Semigroup(Hello, World!)
Semigroup(1).concat(3); // => Semigroup(4)
Semigroup(1).concat('3'); // TypeError
Semigroup(undefined).concat(undefined); // => Semigroup(undefined)
Semigroup(undefined).concat(null); // TypeError
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment