Compare commits
No commits in common. "e9216cc3e48b47f53ad7e95be0f95b35496757d5" and "e83fcd0b4de739380dfadd58b26c815a24038add" have entirely different histories.
e9216cc3e4
...
e83fcd0b4d
@ -1,29 +1,36 @@
|
|||||||
import { type CursorPos } from 'node:readline'
|
import { type CursorPos } from 'node:readline'
|
||||||
import type { Either } from '../util/basic/either'
|
import type { Either } from '../util/basic/either'
|
||||||
import { none, type Option, some } from '../util/basic/option'
|
import {
|
||||||
import { type Tag } from '../util/basic/utility'
|
DoOption,
|
||||||
import { type CanvasEnd, type CanvasOrigin, end, origin } from './canvas'
|
getOrElse,
|
||||||
|
none,
|
||||||
|
type Option,
|
||||||
|
some,
|
||||||
|
} from '../util/basic/option'
|
||||||
|
import { hasTag, pipe, type Tag } from '../util/basic/utility'
|
||||||
|
import {
|
||||||
|
type CanvasEnd,
|
||||||
|
type CanvasOrigin,
|
||||||
|
cursorPos,
|
||||||
|
end,
|
||||||
|
origin,
|
||||||
|
} from './canvas'
|
||||||
|
|
||||||
interface PainterExit<E> extends Tag<'PainterExit'> {
|
interface PainterExit extends Tag<'PainterExit'> {}
|
||||||
value: Either<E, Error>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PainterTask<E, T extends object = {}> extends Tag<'PainterTask'> {
|
interface PainterTask<T extends object = {}> extends Tag<'PainterTask'> {
|
||||||
task: {
|
task: {
|
||||||
origin: CanvasOrigin,
|
origin: CanvasOrigin,
|
||||||
end: CanvasEnd,
|
end: CanvasEnd,
|
||||||
effect: PainterEffect<E, T>,
|
effect: PainterEffect<T & Tag<'PainterState'>>,
|
||||||
state: Option<T & Tag<'PainterState'>>,
|
state: Option<T & Tag<'PainterState'>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type TaskConstructor = (
|
type TaskConstructor<T extends object = {}> = (
|
||||||
x: CursorPos,
|
x: CursorPos,
|
||||||
y: CursorPos,
|
y: CursorPos,
|
||||||
) => <E = number, T extends object = {}>(
|
) => (f: PainterEffect, state?: T & Tag<'PainterState'>) => PainterTask<T>
|
||||||
f: PainterEffect<E, T>,
|
|
||||||
state?: T & Tag<'PainterState'>,
|
|
||||||
) => PainterTask<E, T>
|
|
||||||
const task: TaskConstructor = (x, y) => (f, state?) => {
|
const task: TaskConstructor = (x, y) => (f, state?) => {
|
||||||
return {
|
return {
|
||||||
_tag: 'PainterTask',
|
_tag: 'PainterTask',
|
||||||
@ -36,22 +43,59 @@ const task: TaskConstructor = (x, y) => (f, state?) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExitConstructor = <T>(x: Either<T, Error>) => PainterExit<T>
|
|
||||||
const exit: ExitConstructor = x => ({_tag: 'PainterExit', value: x})
|
|
||||||
|
|
||||||
type PainterEffect<
|
type PainterEffect<
|
||||||
E,
|
|
||||||
T extends object = {},
|
T extends object = {},
|
||||||
> = (task: PainterTask<T>) => Either<PainterTask<T>, PainterExit<E>>
|
> = (task: PainterTask<T>) => Either<PainterTask<T>, PainterExit>
|
||||||
|
|
||||||
type EffectState = <T extends object = {}>(x: T) => T & Tag<'PainterState'>
|
type EffectState = <T extends object = {}>(x: T) => T & Tag<'PainterState'>
|
||||||
const effectState: EffectState = x => ({_tag: 'PainterState', ...x})
|
const effectState: EffectState = x => ({_tag: 'PainterState', ...x})
|
||||||
|
|
||||||
export {
|
export { type PainterEffect, task }
|
||||||
type EffectState as PainterState,
|
|
||||||
effectState as tagState,
|
//
|
||||||
exit,
|
// testing
|
||||||
type PainterEffect,
|
//
|
||||||
type PainterTask,
|
|
||||||
task,
|
type TestEffect = (x: PainterTask<{message: Option<string>}>) => PainterTask<
|
||||||
|
{message: Option<string>}
|
||||||
|
>
|
||||||
|
const testEffect: PainterEffect<{message: string, counter: number}> = x => {
|
||||||
|
const state = DoOption.start()
|
||||||
|
.bind('state', x.task.state)
|
||||||
|
.doL(ctx => {
|
||||||
|
console.log('Message:', ctx.state.message)
|
||||||
|
return some(undefined)
|
||||||
|
})
|
||||||
|
.doL(ctx => {
|
||||||
|
console.log('Counter:', ctx.state.counter)
|
||||||
|
return some(undefined)
|
||||||
|
})
|
||||||
|
.return(ctx =>
|
||||||
|
(ctx.state.counter < 100000)
|
||||||
|
? {...ctx.state, counter: ctx.state.counter + 1}
|
||||||
|
: none
|
||||||
|
)
|
||||||
|
if (pipe(state, getOrElse(none), hasTag('None'))) return {_tag: 'PainterExit'}
|
||||||
|
|
||||||
|
return task(x.task.origin.value, x.task.end.value)(
|
||||||
|
x.task.effect,
|
||||||
|
getOrElse(none)(state),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const textTask = task<{message: string, counter: number}>(
|
||||||
|
cursorPos(2)(0),
|
||||||
|
cursorPos(4)(0),
|
||||||
|
)(
|
||||||
|
testEffect,
|
||||||
|
{
|
||||||
|
_tag: 'PainterState',
|
||||||
|
message: 'test message',
|
||||||
|
counter: 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
const testFn = (x: PainterTask | PainterExit) => {
|
||||||
|
return hasTag('PainterExit')(x) ? 'Exit' : testFn(x.task.effect(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
testFn(textTask)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user