-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add @siteimprove/alfa-selective package (#702)
- Loading branch information
1 parent
6cd0f92
commit 00f1263
Showing
6 changed files
with
234 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"$schema": "http://json.schemastore.org/package", | ||
"name": "@siteimprove/alfa-selective", | ||
"homepage": "https://siteimprove.com", | ||
"version": "0.10.0", | ||
"license": "MIT", | ||
"description": "An implementation of a selective functor for modelling conditional function application", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/siteimprove/alfa.git", | ||
"directory": "packages/alfa-selective" | ||
}, | ||
"bugs": "https://github.com/siteimprove/alfa/issues", | ||
"main": "src/index.js", | ||
"types": "src/index.d.ts", | ||
"files": [ | ||
"src/**/*.js", | ||
"src/**/*.d.ts" | ||
], | ||
"dependencies": { | ||
"@siteimprove/alfa-either": "^0.10.0", | ||
"@siteimprove/alfa-equatable": "^0.10.0", | ||
"@siteimprove/alfa-functor": "^0.10.0", | ||
"@siteimprove/alfa-hash": "^0.10.0", | ||
"@siteimprove/alfa-json": "^0.10.0", | ||
"@siteimprove/alfa-mapper": "^0.10.0", | ||
"@siteimprove/alfa-predicate": "^0.10.0", | ||
"@siteimprove/alfa-refinement": "^0.10.0" | ||
}, | ||
"devDependencies": { | ||
"@siteimprove/alfa-test": "^0.10.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public", | ||
"registry": "https://npm.pkg.github.com/" | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./selective"; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { Either, Left, Right } from "@siteimprove/alfa-either"; | ||
import { Equatable } from "@siteimprove/alfa-equatable"; | ||
import { Functor } from "@siteimprove/alfa-functor"; | ||
import { Hash, Hashable } from "@siteimprove/alfa-hash"; | ||
import { Serializable } from "@siteimprove/alfa-json"; | ||
import { Mapper } from "@siteimprove/alfa-mapper"; | ||
import { Predicate } from "@siteimprove/alfa-predicate"; | ||
import { Refinement } from "@siteimprove/alfa-refinement"; | ||
|
||
export class Selective<S, T = never> | ||
implements | ||
Functor<T>, | ||
Iterable<S | T>, | ||
Equatable, | ||
Hashable, | ||
Serializable<Selective.JSON<S, T>> { | ||
public static of<T>(value: T): Selective<T> { | ||
return new Selective(Left.of(value)); | ||
} | ||
|
||
private readonly _value: Either<S, T>; | ||
|
||
private constructor(value: Either<S, T>) { | ||
this._value = value; | ||
} | ||
|
||
public map<U>(mapper: Mapper<T, U>): Selective<S, U> { | ||
return new Selective( | ||
this._value.either( | ||
(value) => Left.of(value) as Either<S, U>, | ||
(value) => Right.of(mapper(value)) | ||
) | ||
); | ||
} | ||
|
||
public if<P extends S, U>( | ||
refinement: Refinement<S, P>, | ||
mapper: Mapper<P, U> | ||
): Selective<Exclude<S, P>, T | U>; | ||
|
||
public if<U>( | ||
predicate: Predicate<S>, | ||
mapper: Mapper<S, U> | ||
): Selective<S, T | U>; | ||
|
||
public if<U>( | ||
predicate: Predicate<S>, | ||
mapper: Mapper<S, U> | ||
): Selective<S, T | U> { | ||
return this._value.either( | ||
(value) => | ||
predicate(value) ? new Selective(Right.of(mapper(value))) : this, | ||
() => this | ||
); | ||
} | ||
|
||
public else<U>(mapper: Mapper<S, U>): Selective<never, T | U> { | ||
return new Selective<never, T | U>( | ||
Right.of( | ||
this._value.either<T | U>( | ||
(value) => mapper(value), | ||
(value) => value | ||
) | ||
) | ||
); | ||
} | ||
|
||
public get(): S | T { | ||
return this._value.get(); | ||
} | ||
|
||
public equals<S, T>(value: Selective<S, T>): boolean; | ||
|
||
public equals(value: unknown): value is this; | ||
|
||
public equals(value: unknown): boolean { | ||
return value instanceof Selective && value._value.equals(this._value); | ||
} | ||
|
||
public hash(hash: Hash): void { | ||
this._value.hash(hash); | ||
} | ||
|
||
public *iterator(): Iterator<S | T> { | ||
yield this._value.get(); | ||
} | ||
|
||
public [Symbol.iterator](): Iterator<S | T> { | ||
return this.iterator(); | ||
} | ||
|
||
public toJSON(): Selective.JSON<S, T> { | ||
return this._value.toJSON(); | ||
} | ||
|
||
public toString(): string { | ||
return `Selective { ${this._value} }`; | ||
} | ||
} | ||
|
||
export namespace Selective { | ||
export type JSON<S, T = never> = Either.JSON<S, T>; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { test } from "@siteimprove/alfa-test"; | ||
|
||
import { Refinement } from "@siteimprove/alfa-refinement"; | ||
|
||
import { Selective } from "../src/selective"; | ||
|
||
const isFoo: Refinement<string, "foo"> = (string): string is "foo" => | ||
string === "foo"; | ||
|
||
const isBar: Refinement<string, "bar"> = (string): string is "bar" => | ||
string === "bar"; | ||
|
||
test("#if() conditionally applies a function to a selective value", (t) => { | ||
Selective.of("foo") | ||
.if(isFoo, (value) => { | ||
t.equal(value, "foo"); | ||
}) | ||
.if(isBar, () => { | ||
t.fail(); | ||
}); | ||
}); | ||
|
||
test(`#else() applies a function to a selective value that matched no other | ||
conditions`, (t) => { | ||
Selective.of("bar") | ||
.if(isFoo, () => { | ||
t.fail(); | ||
}) | ||
.else((value) => { | ||
t.equal(value, "bar"); | ||
}); | ||
}); | ||
|
||
test("#get() returns the value of a selective", (t) => { | ||
t.equal( | ||
Selective.of("foo") | ||
.if(isFoo, () => "was foo") | ||
.get(), | ||
"was foo" | ||
); | ||
|
||
t.equal( | ||
Selective.of("bar") | ||
.if(isFoo, () => "was foo") | ||
.get(), | ||
"bar" | ||
); | ||
}); | ||
|
||
test(`#map() applies a function to a matched selective value`, (t) => { | ||
t.equal( | ||
Selective.of("foo") | ||
.if(isFoo, () => "was foo") | ||
.map((string) => string.toUpperCase()) | ||
.get(), | ||
"WAS FOO" | ||
); | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"$schema": "http://json.schemastore.org/tsconfig", | ||
"extends": "../tsconfig.json", | ||
"files": ["src/index.ts", "src/selective.ts", "test/selective.spec.ts"], | ||
"references": [ | ||
{ | ||
"path": "../alfa-either" | ||
}, | ||
{ | ||
"path": "../alfa-equatable" | ||
}, | ||
{ | ||
"path": "../alfa-functor" | ||
}, | ||
{ | ||
"path": "../alfa-hash" | ||
}, | ||
{ | ||
"path": "../alfa-json" | ||
}, | ||
{ | ||
"path": "../alfa-mapper" | ||
}, | ||
{ | ||
"path": "../alfa-predicate" | ||
}, | ||
{ | ||
"path": "../alfa-refinement" | ||
}, | ||
{ | ||
"path": "../alfa-test" | ||
} | ||
] | ||
} |
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