aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/effect.ts89
-rw-r--r--stdlib/test.ts45
2 files changed, 133 insertions, 1 deletions
diff --git a/stdlib/effect.ts b/stdlib/effect.ts
index 4a994c4..7eb557c 100644
--- a/stdlib/effect.ts
+++ b/stdlib/effect.ts
@@ -57,16 +57,105 @@ export type Func<Inp = unknown, Out = unknown> =
| Kind1<Inp, Out>
| (<_T extends Inp>() => Out)
+/**
+ * Monadic bind an effect to a function (Equivalent to haskell's >>= operator)
+ *
+ * @typeParam _Eff - Effect to evaluate first
+ * @typeParam _Fn - Function to call with the result of _Eff
+ *
+ * @example
+ * ```ts
+ * type main = Bind<
+ * ReadFile<"./file.txt">,
+ * <contents extends string>() => Print<contents>
+ * >
+ * ```
+ */
export interface Bind<_Eff extends Effect, _Fn extends Func> extends Effect {}
+/**
+ * Bind result of evaluating an effect to a label (Equivalent to haskell's <- syntax)
+ *
+ * Note: labels are scoped to outermost Do, Bind, Try, etc scopes
+ *
+ * @typeParam _Name - The name of label
+ * @typeParam _Eff - Effect to evaluate
+ *
+ * @example
+ * ```ts
+ * type main = Do<[
+ * // contents <- readFile "./file.txt"
+ * BindTo<"contents", ReadFile<"./file.txt">>,
+ * Bind<Label<"contents">, <c extends string>() => Print<c>>
+ * ]>
+ * ```
+ */
export interface BindTo<_Name extends string, _Eff extends Effect>
extends Effect {}
+
+/**
+ * Access a label defined with {@link BindTo}
+ *
+ * @typeParam _Name - The name of label
+ *
+ * @example
+ * ```ts
+ * type main = Do<[
+ * BindTo<"contents", ReadFile<"./file.txt">>,
+ * Bind<Label<"contents">, <c extends string>() => Print<c>>
+ * ]>
+ * ```
+ */
export interface Label<_Name extends string> extends Effect {}
+/**
+ * Evaluate a sequence of effects in series and get the list of results
+ *
+ * @typeParam _Effs - List of effects
+ *
+ * @example
+ * ```ts
+ * type main = Bind<
+ * Seq<[ Pure<1>, ReadFile<"./foobar.txt"> ]>,
+ * <t extends [number, string]>() => Print<t>
+ * >
+ * ```
+ */
export interface Seq<_Effs extends Effect[]> extends Effect {}
+/**
+ * Evaluate a sequence of effects in series and get the result of the last effect (Equivalent to haskell's do syntax)
+ *
+ * @typeParam _Effs - List of effects
+ *
+ * @example
+ * ```ts
+ * type main = Bind<
+ * Do<[ Pure<1>, ReadFile<"./foobar.txt"> ]>,
+ * <t extends string>() => Print<t>
+ * >
+ * ```
+ */
export interface Do<_Effs extends Effect[]> extends Effect {}
+/**
+ * Wrap a value inside an effect (Equivalent to haskell's pure function)
+ *
+ * @typeParam V - Value
+ *
+ * @example
+ * ```ts
+ * type main = Bind<Pure<1>, <t extends number>() => Print<t>>
+ * ```
+ */
export interface Pure<V> extends Effect<V> {}
+/**
+ * Noop effect that does nothing (returns undefined)
+ *
+ * @example
+ * ```ts
+ * type main = Bind<Noop, <t extends undefined>() => Print<t>>
+ * ```
+ */
export interface Noop extends Effect {}
diff --git a/stdlib/test.ts b/stdlib/test.ts
index a3b1d80..bc275aa 100644
--- a/stdlib/test.ts
+++ b/stdlib/test.ts
@@ -19,17 +19,60 @@ import { Equals } from './util'
*/
export interface Assert<_B extends boolean> extends Effect {}
-export interface Test<_m extends string, _effs extends Effect[]>
+/**
+ * Create a test block
+ *
+ * @typeParam _M - description of the test
+ * @typeParam _Effs - List of effects to evaluate
+ *
+ * @example
+ * ```ts
+ * type main = [
+ * Test<"should check if result is 21", [
+ * Bind<EvalSomeEffect<2, 3>, <a extends number>() => AssertEquals<a, 21>>,
+ * // equivalent to...
+ * Bind<EvalSomeEffect<2, 3>, AssertEqualsK<21>>,
+ * ]>
+ * ]
+ * ```
+ */
+export interface Test<_M extends string, _Effs extends Effect[]>
extends Effect {}
export interface ShowAssertionError<_L extends unknown, _R extends unknown>
extends Effect {}
+/**
+ * Assert if left and right values are equal structurally
+ *
+ * @typeParam _Left - Left value
+ * @typeParam _Right - Right value
+ *
+ * @example
+ * ```ts
+ * type main = [
+ * AssertEquals<`Foo ${'bar'}`, 'Foo bar'>
+ * AssertEquals<[2, ...[3, 4]], [2, 3, 4]>
+ * ]
+ * ```
+ */
export type AssertEquals<Left, Right> = Try<
Assert<Equals<Left, Right>>,
<m>() => Do<[ShowAssertionError<Left, Right>, Throw<m>]>
>
+/**
+ * An alternate point-free api for {@link AssertEquals}
+ *
+ * @typeParam _Right - Right value
+ *
+ * @example
+ * ```ts
+ * type main = [
+ * Bind<JsExpr<'21 * 3'>, AssertEqualsK<63>>
+ * ]
+ * ```
+ */
export interface AssertEqualsK<Right extends unknown> extends Kind1 {
return: AssertEquals<this['input'], Right>
}