Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions scripts/comonad.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

createLib('comonad', lib => {

lib.expect('comonad', 'fun');

const fun = lib.importAs('fun', { id: 'id', compose: 'compose' });


// Comonad Instance Creation
const create = (fmap, extract, duplicate, extend) => {

const seq2 = (wa, wb) => extend(_ => extract(mb))(wa);

const seq = (...ws) => (ws.length === 0) ? undefined : ws.reduce(seq2);

/* (w b -> c) -> (w a -> b) -> (w a -> c) */
const cokleisli2 = (wg, wf) => a => fun.compose(mg, extend(mf));

const cokleisli = (...wfs) => wfs.reduce(cokleisli2, extract);

// TODO: Figure out why this is not equivalent.
/* w (a -> b) -> w a -> w b */
// const app = fun.compose(extract, fmap(fmap));

const app = (wf, wa) => extend(
fun.compose(extract(wf), extract))
(wa);



// Comonad Object
return lib.exports(
lib.exp(fmap, 'fmap'),
lib.exp(extract, 'extract'),
lib.exp(duplicate, 'duplicate'),
lib.exp(extend, 'extend'),
lib.exp(cokleisli, 'cokleisli', 'cok'),
lib.exp(seq, 'seq'),
lib.exp(app, 'app')
);
};

const create1 = (fmap, extract, duplicate) =>
create(
fmap,
extract,
duplicate,
/* extend */ f => fun.compose(fmap(f), duplicate)
);

const create2 = (extract, extend) =>
create(
/* fmap */ f => extend(fun.compose(f, extract)),
extract,
/* join */ extend(fun.id),
extend
);


// Library
return lib.exports(
lib.exp(create, 'create'),
lib.exp(create1, 'create1'),
lib.exp(create2, 'create2')
);
});
169 changes: 83 additions & 86 deletions scripts/expr.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@

function exprLib(pair, list, tree, parse) {
createLib('expr', lib => {

lib.expect('expr', 'pair', 'list', 'tree', 'parse');

const [ pair ] = lib.use('pair');

const list = lib.importAs('list', {
nil: 'nil',
cons: 'cons',
build: 'build',
foldr: 'foldr',
monad: 'monad',
concat: 'concat',
index: 'index',
contains: 'contains'
});

const tree = lib.importAs('tree', {
leaf: 'leaf',
node: 'node',
foldr: 'foldr',
label: 'label'
})

// Expression Values
const exprValue = (type, value) => Object.freeze({
Expand Down Expand Up @@ -137,18 +159,18 @@ function exprLib(pair, list, tree, parse) {


// Traversal
const skipLabel = tree.labels.build('skip', null);
const skipLabel = tree.label.build('skip', null);

const traversalOrder = tree.foldr(
taggedEv => list.produce(taggedEv),
taggedEv => list.build(taggedEv),
(taggedEv, css) => {
const cs = list.join(css);
const cs = list.monad.join(css);

const dontTraverse = tag => tag === skipLabel;

const skip = list.contains(dontTraverse, tree.labels.getLabels(taggedEv))
const skip = list.contains(dontTraverse, tree.label.getLabels(taggedEv))

return matchType(tree.labels.getValue(taggedEv))(
return matchType(tree.label.getValue(taggedEv))(
// Leaves don't need definitions
number => undefined,
variable => undefined,
Expand All @@ -166,7 +188,7 @@ function exprLib(pair, list, tree, parse) {
(skip ? cs :
matchFixity(binaryOp)(
prefix => list.cons(taggedEv, cs),
infix => list.concat(list.head(css), list.cons(taggedEv, list.join(list.tail(css)))),
infix => list.concat(list.head(css), list.cons(taggedEv, list.monad.join(list.tail(css)))),
postfix => list.append(taggedEv, cs)
))
);
Expand All @@ -180,89 +202,64 @@ function exprLib(pair, list, tree, parse) {
(itemPair, result) =>
pair.match(itemPair)(
(pos, taggedEv) =>
tree.labels.add(
tree.labels.build('pos', pos),
tree.labels.getValue(taggedEv)
tree.label.add(
tree.label.build('pos', pos),
tree.label.getValue(taggedEv)
)(result)
)
)(list.index(traversalOrder(labeledExpr)));


// Library
return Object.freeze({
__proto__: null,

get: Object.freeze({
__proto__: null,

type: type,
value: value,
symbol: symbol,
fixity: fixity,

traversal: traversalOrder
}),

render: Object.freeze({
__proto__: null,

header: header,
asString: asString
}),

label: Object.freeze({
__proto__: null,

skip: skipLabel,

pos: labelPosition
}),

prefix: prefix,
infix: infix,
postfix: postfix,

voidOp: voidOp,
unaryOp: unaryOp,
binaryOp: binaryOp,
isOperator: isOperator,
isOp: isOperator,

lookupOp: lookupOp,

matchType: matchType,
matchFixity: matchFixity,

number: number,
num: number,
return lib.exports(
lib.exp(lib.exports(
lib.exp(type, 'type'),
lib.exp(value, 'value'),
lib.exp(symbol, 'symbol'),
lib.exp(fixity, 'fixity'),

lib.exp(traversalOrder, 'traversal')
),
'get'),

lib.exp(lib.exports(
lib.exp(header, 'header'),
lib.exp(asString, 'asString', 'str')
),
'render'),

lib.exp(lib.exports(
lib.exp(skipLabel, 'skip'),
lib.exp(labelPosition, 'pos')
),
'label'),

lib.exp(prefix, 'prefix'),
lib.exp(infix, 'infix'),
lib.exp(postfix, 'postfix'),

lib.exp(voidOp, 'voidOp', 'op0'),
lib.exp(unaryOp, 'unaryOp', 'op1'),
lib.exp(binaryOp, 'binaryOp', 'op2'),

lib.exp(isOperator, 'isOperator', 'isOp'),

lib.exp(lookupOp, 'lookupOp'),

lib.exp(matchType, 'matchType'),
lib.exp(matchFixity, 'matchFixity'),

lib.exp(placeholder, 'placeholder'),
lib.exp(number, 'number', 'num'),
lib.exp(variable, 'variable', 'ind'),

variable: variable,
ind: variable,

negative: neg,
neg: neg,

openParen: open,
open: open,

closeParen: close,
close: close,

add: add,

subtract: sub,
sub: sub,

multiply: mult,
mult: mult,

divide: div,
div: div,

raise: exp,
exp: exp,
pow: exp,

placeholder: placeholder
});
}
lib.exp(neg, 'negative', 'neg'),
lib.exp(open, 'openParen', 'open'),
lib.exp(close, 'closeParen', 'close'),
lib.exp(add, 'add', 'sum'),
lib.exp(sub, 'sub', 'subtract'),
lib.exp(mult, 'mult', 'multiply'),
lib.exp(div, 'div', 'divide'),
lib.exp(exp, 'exp', 'pow', 'raise')
);
});
57 changes: 57 additions & 0 deletions scripts/fun.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@


createLib('fun', lib => {

// Primitives
const id = x => x;

const constant = y => x => y;


// Composition
const compose2 = (g, f) => x => g(f(x));

const compose = (...fs) => fs.reduce(compose2, id);

/* (a -> b) -> (b -> x) -> (a -> x) */
const pullback = along => f => compose(f, along);

/* (a -> b) -> (x -> a) -> (x -> b) */
const pushforward = along => f => compose(along, f);


// Currying
const curry2 = pf => {
if (pf.length === 2)
return x => y => pf(x, y);
else
throw "A function of arity != 2 was given to 'curry2'";
};

const uncurry2 = cf => {
if (cf.length === 1)
return (x, y) => {
const tmp = cf(x);
if (tmp(x).length === 1)
return tmp(y);
else
throw "A function of arity != 1 was given to 'uncurry2'";
};
else
throw "A function of arity != 1 was given to 'uncurry2'";
};


// Library
return lib.exports(
lib.exp(id, 'id', 'identity'),
lib.exp(constant, 'constant'),

lib.exp(compose, 'k', 'compose'),
lib.exp(pullback, 'pullback', 'contramap'),
lib.exp(pushforward, 'pushforward', 'fmap'),

lib.exp(curry2, 'curry'),
lib.exp(uncurry2, 'uncurry'),
);
});
Loading