Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 62b9246

Browse files
committed
Curry trix.
1 parent 03c7f90 commit 62b9246

File tree

7 files changed

+87
-46
lines changed

7 files changed

+87
-46
lines changed

apps/api/Tasks/Update.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as T from "@effect-ts/core/Effect"
2-
import { constant, identity } from "@effect-ts/core/Function"
1+
import { flow, identity } from "@effect-ts/core/Function"
2+
import * as T from "@effect-ts-app/core/ext/Effect"
33
import * as O from "@effect-ts-app/core/ext/Option"
44
import { handle } from "@effect-ts-app/infra/app"
55
import { Tasks } from "@effect-ts-demo/todo-client"
@@ -27,7 +27,10 @@ export default handle(Tasks.Update)(({ id, myDay, ..._ }) =>
2727

2828
// TODO: Context should perhaps know if changed, and should use a transaction
2929
yield* $(
30-
T.tuple(whenChanged(Tasks.save_)(nt, task), whenChanged(Users.save)(nu, user))
30+
T.tuple(
31+
Tasks.save_["|>"](T.ifDiff(nt, task)),
32+
Users.save["|>"](T.ifDiff(nu, user))
33+
)
3134
)
3235
})
3336
)
@@ -54,20 +57,12 @@ export function updateTask_(
5457
O.fold(
5558
// TODO: Attachment removed?
5659
() => t,
57-
(a) =>
58-
t["|>"](
59-
Task.addAudit(
60-
TaskAudits.TaskFileAdded.fromAttachment(a)({ userId: user.id })
61-
)
62-
)
60+
flow(
61+
TaskAudits.TaskFileAdded.fromAttachment({ userId: user.id }),
62+
Task.addAuditR(t)
63+
)
6364
)
6465
)
6566
}
6667
return [t, user] as const
6768
}
68-
69-
function whenChanged<I, R, E, A>(f: (i: I) => T.Effect<R, E, A>) {
70-
return (n: I, orig: I) => T.if(() => f(n), constUnit)(n !== orig)
71-
}
72-
73-
const constUnit = constant(T.unit)

apps/api/_services/TodoContext.testdata.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818

1919
function makeUserTaskCreator(u: User) {
2020
return flow(
21-
User.createTask(u),
21+
User.createTaskR(u),
2222
Task.lens["|>"](Lens.prop("title"))["|>"](
2323
Lens.modify((t) => reasonableStringUnsafe(`${u.name} - ${t}`))
2424
)
@@ -48,7 +48,7 @@ export function makeTestDataUnsafe() {
4848

4949
const users = [patrick, mike, markus]
5050

51-
const createPatrickList = User.createTaskList(patrick)
51+
const createPatrickList = User.createTaskListR(patrick)
5252
const patrickList = createPatrickList({
5353
title: reasonableStringUnsafe("Some Patrick List"),
5454
})

packages/core/ext/Effect.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@ import {
55
effectAsyncInterrupt,
66
fail,
77
fromEither,
8+
if_,
89
IO,
910
succeed,
1011
succeedWith,
1112
tap,
13+
unit,
1214
} from "@effect-ts/core/Effect"
1315
import type * as Ei from "@effect-ts/core/Either"
1416
import * as O from "@effect-ts/core/Option"
1517

16-
import { flow, Lazy, pipe } from "./Function"
18+
import { constant, flow, Lazy, pipe } from "./Function"
1719

1820
export const encaseEither = <E, A>(ei: Ei.Either<E, A>) => fromEither(() => ei)
1921
export const chainEither = <E, A, A2>(ei: (a: A2) => Ei.Either<E, A>) =>
@@ -51,4 +53,18 @@ export function tupleCurriedTap<A, B, R, E, C>(f: (b: B) => (a: A) => Effect<R,
5153
return (t: readonly [A, B]) => succeed(t[0])["|>"](tap(f(t[1])))
5254
}
5355

56+
export function ifDiffR<I, R, E, A>(f: (i: I) => Effect<R, E, A>) {
57+
return (n: I, orig: I) => ifDiff_(n, orig, f)
58+
}
59+
60+
export function ifDiff<I, R, E, A>(n: I, orig: I) {
61+
return (f: (i: I) => Effect<R, E, A>) => ifDiff_(n, orig, f)
62+
}
63+
64+
export function ifDiff_<I, R, E, A>(n: I, orig: I, f: (i: I) => Effect<R, E, A>) {
65+
return if_(n !== orig, () => f(n), constUnit)
66+
}
67+
68+
const constUnit = constant(unit)
69+
5470
export * from "@effect-ts/core/Effect"

packages/core/ext/utils/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,19 @@ export function capitalize<T extends string>(string: T): Capitalize<T> {
7070
export function uncapitalize<T extends string>(string: T): Uncapitalize<T> {
7171
return (string.charAt(0).toLowerCase() + string.slice(1)) as Uncapitalize<T>
7272
}
73+
74+
export function tupledCurry<A, B, C>(f: (b: B) => (a: A) => C) {
75+
return (t: [A, B]) => f(t[1])(t[0])
76+
}
77+
78+
export function reverseCurry<A, B, C>(f: (b: B) => (a: A) => C) {
79+
return (a: A) => (b: B) => f(b)(a)
80+
}
81+
82+
export function curry<A, B, C>(f: (a: A, b: B) => C) {
83+
return (b: B) => (a: A) => f(a, b)
84+
}
85+
86+
export function uncurry<A, B, C>(f: (b: B) => (a: A) => C) {
87+
return (a: A, b: B) => f(b)(a)
88+
}

packages/types/Task/Task.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
reasonableString,
2121
withDefault,
2222
} from "@effect-ts-app/core/ext/Schema"
23+
import { curry, reverseCurry, uncurry } from "@effect-ts-app/core/ext/utils"
2324

2425
import { TaskId, TaskListIdU, UserId } from "../ids"
2526
import { TaskAudit, TaskCreated } from "./audit"
@@ -107,9 +108,8 @@ export class Task extends Model<Task>()({
107108

108109
static addAudit = (audit: TaskAudit) =>
109110
Task.lens["|>"](Lens.prop("auditLog"))["|>"](Lens.modify(A.snoc(audit)))
110-
static addAudit_ = (t: Task, audit: TaskAudit) => Task.addAudit(audit)(t)
111-
112-
static update = (_: OptionalEditableTaskProps) => (t: Task) => Task.update_(t, _)
111+
static addAuditR = reverseCurry(Task.addAudit)
112+
static addAudit_ = uncurry(Task.addAudit)
113113

114114
static update_ = (t: Task, _: OptionalEditableTaskProps) => {
115115
const nt = {
@@ -119,4 +119,5 @@ export class Task extends Model<Task>()({
119119
}
120120
return nt
121121
}
122+
static update = curry(Task.update_)
122123
}

packages/types/Task/audit.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { LazyGetter } from "@effect-ts/core/Utils"
12
import {
23
date,
34
defaultProp,
@@ -11,6 +12,7 @@ import {
1112
union,
1213
UUID,
1314
} from "@effect-ts-app/core/ext/Schema"
15+
import { reverseCurry } from "@effect-ts-app/core/ext/utils"
1416

1517
import { UserId } from "../ids"
1618
import { Attachment, FileName } from "./shared"
@@ -34,8 +36,12 @@ export class TaskFileAdded extends Model<TaskFileAdded>()({
3436
...AuditProps("TaskFileAdded"),
3537
fileName: prop(FileName),
3638
}) {
37-
static fromAttachment(a: Attachment) {
38-
return partialConstructor_(TaskFileAdded, { fileName: a.fileName })
39+
static fromAttachmentR = (a: Attachment) =>
40+
partialConstructor_(TaskFileAdded, { fileName: a.fileName })
41+
42+
@LazyGetter()
43+
static get fromAttachment() {
44+
return reverseCurry(TaskFileAdded.fromAttachmentR)
3945
}
4046
}
4147

packages/types/User.ts

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import * as A from "@effect-ts/core/Collections/Immutable/Array"
22
import * as O from "@effect-ts/core/Option"
33
import { Option } from "@effect-ts/core/Option"
4+
import { LazyGetter } from "@effect-ts/core/Utils"
45
import {
56
array,
67
date,
78
defaultProp,
89
Email,
9-
GetPartialConstructor,
1010
Model,
1111
namedC,
1212
ParsedShapeOf,
@@ -16,6 +16,7 @@ import {
1616
props,
1717
reasonableString,
1818
} from "@effect-ts-app/core/ext/Schema"
19+
import { reverseCurry, uncurry } from "@effect-ts-app/core/ext/utils"
1920

2021
import { TaskId, UserId } from "./ids"
2122
import { Task } from "./Task"
@@ -37,32 +38,38 @@ export class User extends Model<User>()({
3738
myDay: defaultProp(array(MyDay)),
3839
phoneNumber: prop(PhoneNumber),
3940
}) {
40-
static createTask__ =
41-
(a: GetPartialConstructor<typeof User["createTask_"]>) => (u: User) =>
42-
User.createTask_(u, a)
41+
@LazyGetter()
42+
static get createTask() {
43+
return reverseCurry(User.createTaskR)
44+
}
4345

44-
static createTask_ = (u: User, a: GetPartialConstructor<typeof User["createTask"]>) =>
45-
User.createTask(u)(a)
46-
static createTask = (u: User) => createPartialTask({ createdBy: u.id })
46+
@LazyGetter()
47+
static get createTask_() {
48+
return uncurry(User.createTask)
49+
}
50+
static createTaskR = (u: User) => createPartialTask({ createdBy: u.id })
4751

48-
static createTaskList__ =
49-
(a: GetPartialConstructor<typeof User["createTaskList_"]>) => (u: User) =>
50-
User.createTaskList_(u, a)
52+
@LazyGetter()
53+
static get createTaskList() {
54+
return reverseCurry(User.createTaskListR)
55+
}
5156

52-
static createTaskList_ = (
53-
u: User,
54-
a: GetPartialConstructor<typeof User["createTaskList"]>
55-
) => User.createTaskList(u)(a)
56-
static createTaskList = (u: User) => createPartialTaskList({ ownerId: u.id })
57+
@LazyGetter()
58+
static get createTaskList_() {
59+
return uncurry(User.createTaskList)
60+
}
61+
static createTaskListR = (u: User) => createPartialTaskList({ ownerId: u.id })
5762

58-
static createTaskListGroup__ =
59-
(a: GetPartialConstructor<typeof User["createTaskListGroup_"]>) => (u: User) =>
60-
User.createTaskListGroup_(u, a)
61-
static createTaskListGroup_ = (
62-
u: User,
63-
a: GetPartialConstructor<typeof User["createTaskListGroup"]>
64-
) => User.createTaskListGroup(u)(a)
65-
static createTaskListGroup = (u: User) =>
63+
@LazyGetter()
64+
static get createTaskListGroup() {
65+
return reverseCurry(User.createTaskListGroupR)
66+
}
67+
68+
@LazyGetter()
69+
static get createTaskListGroup_() {
70+
return uncurry(User.createTaskListGroup)
71+
}
72+
static createTaskListGroupR = (u: User) =>
6673
createPartialTaskListGroup({ ownerId: u.id })
6774

6875
static getMyDay = (t: Task) => (u: User) =>

0 commit comments

Comments
 (0)