@no-day/fp-ts-graph
Advanced tools
Comparing version 0.1.0 to 0.2.0
@@ -140,2 +140,71 @@ /** @since 0.1.0 */ | ||
/** | ||
* Modifies a single edge in the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Combinators | ||
*/ | ||
export declare const modifyAtEdge: <Id>(E: Eq<Id>) => <Edge>(from: Id, to: Id, update: (e: Edge) => Edge) => <Node_1>(graph: Graph<Id, Edge, Node_1>) => option.Option<Graph<Id, Edge, Node_1>>; | ||
/** | ||
* Modifies a single node in the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Combinators | ||
*/ | ||
export declare const modifyAtNode: <Id>(E: Eq<Id>) => <Node_1>(id: Id, update: (n: Node_1) => Node_1) => <Edge>(graph: Graph<Id, Edge, Node_1>) => option.Option<Graph<Id, Edge, Node_1>>; | ||
/** | ||
* Retrieves an edge from the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Utils | ||
* @example | ||
* import Graph, * as graph from '@no-day/fp-ts-graph'; | ||
* import * as fp from 'fp-ts'; | ||
* | ||
* type MyGraph = Graph<string, string, string>; | ||
* | ||
* const myGraph: MyGraph = fp.function.pipe( | ||
* graph.empty<string, string, string>(), | ||
* graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
* graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
* fp.option.of, | ||
* fp.option.chain(graph.insertEdge(fp.string.Eq)('n1', 'n2', 'Edge 1')), | ||
* fp.option.getOrElse(() => graph.empty<string, string, string>()) | ||
* ); | ||
* | ||
* assert.deepStrictEqual( | ||
* fp.function.pipe( | ||
* myGraph, | ||
* graph.lookupEdge(fp.string.Eq)('n1', 'n2'), | ||
* ), | ||
* fp.option.some('Edge 1') | ||
* ); | ||
*/ | ||
export declare const lookupEdge: <Id>(E: Eq<Id>) => (from: Id, to: Id) => <Edge>(graph: Graph<Id, Edge, unknown>) => option.Option<Edge>; | ||
/** | ||
* Retrieves a node from the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Utils | ||
* @example | ||
* import Graph, * as graph from '@no-day/fp-ts-graph'; | ||
* import * as fp from 'fp-ts'; | ||
* | ||
* type MyGraph = Graph<string, string, string>; | ||
* | ||
* const myGraph: MyGraph = fp.function.pipe( | ||
* graph.empty<string, string, string>(), | ||
* graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
* graph.insertNode(fp.string.Eq)('n2', 'Node 2') | ||
* ); | ||
* | ||
* assert.deepStrictEqual( | ||
* fp.function.pipe( | ||
* myGraph, | ||
* graph.lookupNode(fp.string.Eq)('n2'), | ||
* ), | ||
* fp.option.some('Node 2') | ||
* ); | ||
*/ | ||
export declare const lookupNode: <Id>(E: Eq<Id>) => (id: Id) => <Node_1>(graph: Graph<Id, unknown, Node_1>) => option.Option<Node_1>; | ||
/** | ||
* Get nodes as "id"-"value" pairs | ||
@@ -142,0 +211,0 @@ * |
@@ -28,3 +28,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getEqEdgeId = exports.toDotFile = exports.entries = exports.edgeEntries = exports.nodeEntries = exports.map = exports.mapNode = exports.mapEdge = exports.insertEdge = exports.insertNode = exports.empty = void 0; | ||
exports.getEqEdgeId = exports.toDotFile = exports.entries = exports.edgeEntries = exports.nodeEntries = exports.lookupNode = exports.lookupEdge = exports.modifyAtNode = exports.modifyAtEdge = exports.map = exports.mapNode = exports.mapEdge = exports.insertEdge = exports.insertNode = exports.empty = void 0; | ||
var function_1 = require("fp-ts/function"); | ||
@@ -191,3 +191,110 @@ var map_ = __importStar(require("fp-ts/Map")); | ||
exports.map = exports.mapNode; | ||
/** | ||
* Modifies a single edge in the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Combinators | ||
*/ | ||
var modifyAtEdge = function (E) { | ||
return function (from, to, update) { | ||
return function (graph) { | ||
return function_1.pipe(graph.edges, map_.modifyAt(exports.getEqEdgeId(E))({ from: from, to: to }, update), option.map(function (edges) { | ||
return unsafeMkGraph({ nodes: graph.nodes, edges: edges }); | ||
})); | ||
}; | ||
}; | ||
}; | ||
exports.modifyAtEdge = modifyAtEdge; | ||
/** | ||
* Modifies a single node in the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Combinators | ||
*/ | ||
var modifyAtNode = function (E) { | ||
return function (id, update) { | ||
return function (graph) { | ||
return function_1.pipe(graph.nodes, map_.modifyAt(E)(id, function (_a) { | ||
var incoming = _a.incoming, outgoing = _a.outgoing, data = _a.data; | ||
return ({ | ||
incoming: incoming, | ||
outgoing: outgoing, | ||
data: update(data) | ||
}); | ||
}), option.map(function (nodes) { | ||
return unsafeMkGraph({ nodes: nodes, edges: graph.edges }); | ||
})); | ||
}; | ||
}; | ||
}; | ||
exports.modifyAtNode = modifyAtNode; | ||
// ------------------------------------------------------------------------------------- | ||
// utils | ||
// ------------------------------------------------------------------------------------- | ||
/** | ||
* Retrieves an edge from the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Utils | ||
* @example | ||
* import Graph, * as graph from '@no-day/fp-ts-graph'; | ||
* import * as fp from 'fp-ts'; | ||
* | ||
* type MyGraph = Graph<string, string, string>; | ||
* | ||
* const myGraph: MyGraph = fp.function.pipe( | ||
* graph.empty<string, string, string>(), | ||
* graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
* graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
* fp.option.of, | ||
* fp.option.chain(graph.insertEdge(fp.string.Eq)('n1', 'n2', 'Edge 1')), | ||
* fp.option.getOrElse(() => graph.empty<string, string, string>()) | ||
* ); | ||
* | ||
* assert.deepStrictEqual( | ||
* fp.function.pipe( | ||
* myGraph, | ||
* graph.lookupEdge(fp.string.Eq)('n1', 'n2'), | ||
* ), | ||
* fp.option.some('Edge 1') | ||
* ); | ||
*/ | ||
var lookupEdge = function (E) { return function (from, to) { | ||
return function (graph) { | ||
return function_1.pipe(graph.edges, map_.lookup(exports.getEqEdgeId(E))({ from: from, to: to })); | ||
}; | ||
}; }; | ||
exports.lookupEdge = lookupEdge; | ||
/** | ||
* Retrieves a node from the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Utils | ||
* @example | ||
* import Graph, * as graph from '@no-day/fp-ts-graph'; | ||
* import * as fp from 'fp-ts'; | ||
* | ||
* type MyGraph = Graph<string, string, string>; | ||
* | ||
* const myGraph: MyGraph = fp.function.pipe( | ||
* graph.empty<string, string, string>(), | ||
* graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
* graph.insertNode(fp.string.Eq)('n2', 'Node 2') | ||
* ); | ||
* | ||
* assert.deepStrictEqual( | ||
* fp.function.pipe( | ||
* myGraph, | ||
* graph.lookupNode(fp.string.Eq)('n2'), | ||
* ), | ||
* fp.option.some('Node 2') | ||
* ); | ||
*/ | ||
var lookupNode = function (E) { return function (id) { | ||
return function (graph) { | ||
return function_1.pipe(graph.nodes, map_.lookup(E)(id), option.map(function (node) { return node.data; })); | ||
}; | ||
}; }; | ||
exports.lookupNode = lookupNode; | ||
// ------------------------------------------------------------------------------------- | ||
// destructors | ||
@@ -194,0 +301,0 @@ // ------------------------------------------------------------------------------------- |
{ | ||
"name": "@no-day/fp-ts-graph", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/no-day/fp-ts-graph", | ||
@@ -10,16 +10,16 @@ "main": "dist/src/index.js", | ||
"peerDependencies": { | ||
"fp-ts": "^2.9.5" | ||
"fp-ts": "^2.11.1" | ||
}, | ||
"devDependencies": { | ||
"@no-day/fp-ts-graph": "git+https://github.com/no-day/fp-ts-graph", | ||
"@types/jest": "^26.0.20", | ||
"@types/jest": "^27.0.1", | ||
"@types/node": "^14.14.31", | ||
"docs-ts": "^0.6.4", | ||
"doctoc": "^2.0.0", | ||
"fp-ts": "^2.9.5", | ||
"docs-ts": "^0.6.10", | ||
"doctoc": "^2.0.1", | ||
"fp-ts": "^2.11.1", | ||
"jest": "^26.6.3", | ||
"prettier": "^2.2.1", | ||
"ts-jest": "^26.5.2", | ||
"prettier": "^2.3.2", | ||
"ts-jest": "^26.5.6", | ||
"ts-node": "^9.1.1", | ||
"typescript": "^4.2.2" | ||
"typescript": "^4.2.4" | ||
}, | ||
@@ -34,4 +34,4 @@ "scripts": { | ||
"dependencies": { | ||
"prettier-plugin-jsdoc": "^0.3.12" | ||
"prettier-plugin-jsdoc": "^0.3.23" | ||
} | ||
} |
@@ -187,6 +187,2 @@ # fp-ts-graph | ||
- `deleteEdge` | ||
- `updateNode` | ||
- `updateEdge` | ||
- `lookupNode` | ||
- `lookupEdge` | ||
- `outgoingIds` | ||
@@ -193,0 +189,0 @@ - `incomingIds` |
111
src/index.ts
@@ -6,7 +6,6 @@ /** @since 0.1.0 */ | ||
import * as array from 'fp-ts/Array'; | ||
import * as tuple from 'fp-ts/Tuple'; | ||
import * as option from 'fp-ts/Option'; | ||
import { Option } from 'fp-ts/Option'; | ||
import * as set_ from 'fp-ts/Set'; | ||
import { Eq, eqString, getStructEq } from 'fp-ts/Eq'; | ||
import { Eq, getStructEq } from 'fp-ts/Eq'; | ||
@@ -229,3 +228,111 @@ // ------------------------------------------------------------------------------------- | ||
/** | ||
* Modifies a single edge in the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Combinators | ||
*/ | ||
export const modifyAtEdge = <Id>(E: Eq<Id>) => | ||
<Edge>(from: Id, to: Id, update: (e: Edge) => Edge) => | ||
<Node>(graph: Graph<Id, Edge, Node>): Option<Graph<Id, Edge, Node>> => | ||
pipe( | ||
graph.edges, | ||
map_.modifyAt(getEqEdgeId(E))({ from, to }, update), | ||
option.map((edges) => | ||
unsafeMkGraph({ nodes: graph.nodes, edges }) | ||
) | ||
); | ||
/** | ||
* Modifies a single node in the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Combinators | ||
*/ | ||
export const modifyAtNode = <Id>(E: Eq<Id>) => | ||
<Node>(id: Id, update: (n: Node) => Node) => | ||
<Edge>(graph: Graph<Id, Edge, Node>): Option<Graph<Id, Edge, Node>> => | ||
pipe( | ||
graph.nodes, | ||
map_.modifyAt(E)(id, ({ incoming, outgoing, data }) => ({ | ||
incoming, outgoing, data: update(data) | ||
})), | ||
option.map((nodes) => | ||
unsafeMkGraph({ nodes, edges: graph.edges }) | ||
) | ||
); | ||
// ------------------------------------------------------------------------------------- | ||
// utils | ||
// ------------------------------------------------------------------------------------- | ||
/** | ||
* Retrieves an edge from the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Utils | ||
* @example | ||
* import Graph, * as graph from '@no-day/fp-ts-graph'; | ||
* import * as fp from 'fp-ts'; | ||
* | ||
* type MyGraph = Graph<string, string, string>; | ||
* | ||
* const myGraph: MyGraph = fp.function.pipe( | ||
* graph.empty<string, string, string>(), | ||
* graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
* graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
* fp.option.of, | ||
* fp.option.chain(graph.insertEdge(fp.string.Eq)('n1', 'n2', 'Edge 1')), | ||
* fp.option.getOrElse(() => graph.empty<string, string, string>()) | ||
* ); | ||
* | ||
* assert.deepStrictEqual( | ||
* fp.function.pipe( | ||
* myGraph, | ||
* graph.lookupEdge(fp.string.Eq)('n1', 'n2'), | ||
* ), | ||
* fp.option.some('Edge 1') | ||
* ); | ||
*/ | ||
export const lookupEdge = <Id>(E: Eq<Id>) => (from: Id, to: Id) => | ||
<Edge>(graph: Graph<Id, Edge, unknown>): Option<Edge> => | ||
pipe( | ||
graph.edges, | ||
map_.lookup(getEqEdgeId(E))({ from, to }) | ||
); | ||
/** | ||
* Retrieves a node from the graph. | ||
* | ||
* @since 0.2.0 | ||
* @category Utils | ||
* @example | ||
* import Graph, * as graph from '@no-day/fp-ts-graph'; | ||
* import * as fp from 'fp-ts'; | ||
* | ||
* type MyGraph = Graph<string, string, string>; | ||
* | ||
* const myGraph: MyGraph = fp.function.pipe( | ||
* graph.empty<string, string, string>(), | ||
* graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
* graph.insertNode(fp.string.Eq)('n2', 'Node 2') | ||
* ); | ||
* | ||
* assert.deepStrictEqual( | ||
* fp.function.pipe( | ||
* myGraph, | ||
* graph.lookupNode(fp.string.Eq)('n2'), | ||
* ), | ||
* fp.option.some('Node 2') | ||
* ); | ||
*/ | ||
export const lookupNode = <Id>(E: Eq<Id>) => (id: Id) => | ||
<Node>(graph: Graph<Id, unknown, Node>): Option<Node> => | ||
pipe( | ||
graph.nodes, | ||
map_.lookup(E)(id), | ||
option.map((node) => node.data) | ||
); | ||
// ------------------------------------------------------------------------------------- | ||
// destructors | ||
@@ -232,0 +339,0 @@ // ------------------------------------------------------------------------------------- |
@@ -52,2 +52,79 @@ import * as graph from '../src'; | ||
}); | ||
describe("modifyAtEdge", () => { | ||
it("should modify an existing edge", () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
fp.option.of, | ||
fp.option.chain( | ||
graph.insertEdge(fp.string.Eq)('n1', 'n2', 'Edge 1') | ||
), | ||
fp.option.chain( | ||
graph.modifyAtEdge(fp.string.Eq)('n1', 'n2', | ||
(e) => `${e} updated`) | ||
), | ||
fp.option.map(graph.edgeEntries) | ||
), | ||
fp.option.some([ | ||
[{ from: 'n1', to: 'n2' }, 'Edge 1 updated'] | ||
]) | ||
); | ||
}); | ||
it("should not modify a non-existing edge", () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
fp.option.of, | ||
fp.option.chain( | ||
graph.insertEdge(fp.string.Eq)('n1', 'n2', 'Edge 1') | ||
), | ||
fp.option.chain( | ||
graph.modifyAtEdge(fp.string.Eq)('n2', 'n1', | ||
(e) => `${e} updated`) | ||
), | ||
fp.option.map(graph.edgeEntries) | ||
), | ||
fp.option.none | ||
); | ||
}); | ||
}) | ||
describe("modifyAtNode", () => { | ||
it("should modify an existing node", () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
graph.modifyAtNode(fp.string.Eq)('n2', | ||
(n) => `${n} updated`), | ||
fp.option.map(graph.nodeEntries) | ||
), | ||
fp.option.some([ | ||
['n1', 'Node 1'], | ||
['n2', 'Node 2 updated'] | ||
]) | ||
); | ||
}); | ||
it("shouldn't modify a non-existing node", () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
graph.modifyAtNode(fp.string.Eq)('n3', | ||
(n) => `${n} updated`), | ||
fp.option.map(graph.nodeEntries) | ||
), | ||
fp.option.none | ||
); | ||
}); | ||
}) | ||
}); | ||
@@ -291,2 +368,74 @@ | ||
}); | ||
describe('Utils', () => { | ||
describe('lookupEdge', () => { | ||
it('should return an existing edge', () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
graph.insertNode(fp.string.Eq)('n3', 'Node 3'), | ||
fp.option.of, | ||
fp.option.chain( | ||
graph.insertEdge(fp.string.Eq)('n1', 'n2', 'Edge 1') | ||
), | ||
fp.option.chain( | ||
graph.insertEdge(fp.string.Eq)('n2', 'n3', 'Edge 2') | ||
), | ||
fp.option.chain( | ||
graph.lookupEdge(fp.string.Eq)('n1', 'n2') | ||
) | ||
), | ||
fp.option.some('Edge 1') | ||
) | ||
}) | ||
it('should return none for non-existing edge', () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.insertNode(fp.string.Eq)('n2', 'Node 2'), | ||
graph.insertNode(fp.string.Eq)('n3', 'Node 3'), | ||
fp.option.of, | ||
fp.option.chain( | ||
graph.insertEdge(fp.string.Eq)('n1', 'n2', 'Edge 1') | ||
), | ||
fp.option.chain( | ||
graph.insertEdge(fp.string.Eq)('n2', 'n3', 'Edge 2') | ||
), | ||
fp.option.chain( | ||
graph.lookupEdge(fp.string.Eq)('n3', 'n2') | ||
) | ||
), | ||
fp.option.none | ||
) | ||
}) | ||
}) | ||
describe('lookupNode', () => { | ||
it('should return an existing node value', () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.lookupNode(fp.string.Eq)('n1') | ||
), | ||
fp.option.some('Node 1') | ||
) | ||
}) | ||
it('should lookup none for non-existing node', () => { | ||
deepStrictEqual( | ||
fp.function.pipe( | ||
graph.empty<string, string, string>(), | ||
graph.insertNode(fp.string.Eq)('n1', 'Node 1'), | ||
graph.lookupNode(fp.string.Eq)('n2') | ||
), | ||
fp.option.none | ||
) | ||
}) | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
71051
1755
196
+ Addedfp-ts@2.16.6(transitive)
- Removedfp-ts@2.16.5(transitive)