From 75368c8ef8462c9eb60e9ea075982ea5c9634906 Mon Sep 17 00:00:00 2001 From: Eric Rumsey Date: Tue, 27 May 2025 16:31:00 -0500 Subject: [PATCH] Add Do notation for option --- src/lib/util/basic/option.ts | 39 +++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/lib/util/basic/option.ts b/src/lib/util/basic/option.ts index 165c0c1..a036e00 100644 --- a/src/lib/util/basic/option.ts +++ b/src/lib/util/basic/option.ts @@ -10,9 +10,8 @@ export const some = (value: A): Option => ({ }) // Operations -export const map = - (f: (a: A) => B) => (fa: Option): Option => - fa._tag === 'Some' ? some(f(fa.value)) : none +export const map = (f: (a: A) => B) => (fa: Option): Option => + fa._tag === 'Some' ? some(f(fa.value)) : none export const chain = (f: (a: A) => Option) => (fa: Option): Option => @@ -20,3 +19,37 @@ export const chain = export const getOrElse = (defaultValue: A) => (fa: Option): A => fa._tag === 'Some' ? fa.value : defaultValue + +export class DoOption> { + constructor(private readonly option: Option) {} + + bind(key: K, fa: Option): DoOption> { + const newOption = chain((scope: T) => + map((a: A) => ({...scope, [key]: a}))(fa) + )(this.option) + return new DoOption(newOption as Option>) + } + + return(f: (scope: T) => B): Option { + return map(f)(this.option) + } + + done(): Option { + return this.option + } + do(fa: Option): DoOption { + const newOption = chain((scope: T) => map(() => scope)(fa))(this.option) + return new DoOption(newOption) + } + + doL(f: (scope: T) => Option): DoOption { + const newOption = chain((scope: T) => map(() => scope)(f(scope)))( + this.option, + ) + return new DoOption(newOption) + } + + static start(): DoOption<{}> { + return new DoOption(some({})) + } +}