Skip to content

Commit

Permalink
naryFmap 定义 lift
Browse files Browse the repository at this point in the history
  • Loading branch information
xieyuheng committed Jun 23, 2024
1 parent 582df46 commit 0aeb78f
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 8 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
用 generic 函数定义 lift -- 删除 `skipIncompleteInputs`
删除 `skipIncompleteInputs`
monads/supported-monad -- 删除 `maybeUnwrapSupported`

> propagator 支持 dependencies for provenance
Expand Down
28 changes: 25 additions & 3 deletions src/monad/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
import { defineGeneric } from "../generic/index.js"

export const fmap = defineGeneric({ default: (f, mx) => f(mx) })
export const join = defineGeneric({ default: (mmx) => mmx })
export const bind = (mx: any, f: (x: any) => any) => join(fmap(f, mx))
// (f: (A) -> B, ma: M(A)) -> M(B)
export const fmap = defineGeneric({ default: (f, ma) => f(ma) })

// (mma: M(M(A))) -> M(A)
export const join = defineGeneric({ default: (mma) => mma })

// (ma: M(A), f: (A) -> M(B)) -> M(B)
export const bind = (ma: any, f: (x: any) => any) => join(fmap(f, ma))

// (f: (A0, A1, ...) -> B) -> (M(A0), M(A1), ...) -> M(B)
export function naryFmap(
f: (...args: Array<any>) => any,
): (...margs: Array<any>) => any {
return (...margs) => {
function loop(margs: Array<any>, f: (...args: Array<any>) => any): any {
if (margs.length === 0) return f()

return bind(margs[0], (arg) =>
loop(margs.slice(1), (...restArgs) => f(arg, ...restArgs)),
)
}

return loop(margs, f)
}
}
4 changes: 2 additions & 2 deletions src/monads/nothing-monad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { defineHandler } from "../generic/index.js"
import { fmap, join } from "../monad/index.js"
import { isFunction } from "../utils/isFunction.js"

defineHandler(fmap, [isFunction, isNothing], (f, mx) => nothing)
defineHandler(join, [isNothing], (mmx) => nothing)
defineHandler(fmap, [isFunction, isNothing], (f, ma) => nothing)
defineHandler(join, [isNothing], (mma) => nothing)
5 changes: 3 additions & 2 deletions src/propagator/definePrimitive.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Cell, addPropagator, isNothing, nothing, put } from "../cell/index.js"
import { isSupported } from "../dependency/index.js"
import { naryFmap } from "../monad/index.js"
import "../monads/nothing-monad.js"
import { schedule } from "../scheduler/index.js"
import type { MaybePromise } from "../utils/MaybePromise.js"
import { repeatApply } from "../utils/repeatApply.js"
Expand Down Expand Up @@ -87,8 +89,7 @@ function watch(cells: Array<Cell<any>>, propagator: Propagator): void {
function lift(
fn: (...args: Array<any>) => MaybePromise<any>,
): (...args: Array<Cell<any>>) => MaybePromise<any> {
fn = maybeUnwrapSupported(fn)
fn = skipIncompleteInputs(fn)
fn = naryFmap(fn)

return (...inputs) => fn(...inputs.map((input) => input.content))
}
Expand Down

0 comments on commit 0aeb78f

Please sign in to comment.