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

Commit

Permalink
curry trix.
Browse files Browse the repository at this point in the history
  • Loading branch information
patroza committed May 24, 2021
1 parent e99d07a commit 360c404
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 44 deletions.
25 changes: 10 additions & 15 deletions apps/api/Tasks/Update.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as T from "@effect-ts/core/Effect"
import { constant, identity } from "@effect-ts/core/Function"
import { flow, identity } from "@effect-ts/core/Function"
import * as T from "@effect-ts-app/core/ext/Effect"
import * as O from "@effect-ts-app/core/ext/Option"
import { handle } from "@effect-ts-app/infra/app"
import { Tasks } from "@effect-ts-demo/todo-client"
Expand Down Expand Up @@ -27,7 +27,10 @@ export default handle(Tasks.Update)(({ id, myDay, ..._ }) =>

// TODO: Context should perhaps know if changed, and should use a transaction
yield* $(
T.tuple(whenChanged(Tasks.save_)(nt, task), whenChanged(Users.save)(nu, user))
T.tuple(
Tasks.save_["|>"](T.ifDiff(nt, task)),
Users.save["|>"](T.ifDiff(nu, user))
)
)
})
)
Expand All @@ -54,20 +57,12 @@ export function updateTask_(
O.fold(
// TODO: Attachment removed?
() => t,
(a) =>
t["|>"](
Task.addAudit(
TaskAudits.TaskFileAdded.fromAttachment(a)({ userId: user.id })
)
)
flow(
TaskAudits.TaskFileAdded.fromAttachment({ userId: user.id }),
Task.addAuditR(t)
)
)
)
}
return [t, user] as const
}

function whenChanged<I, R, E, A>(f: (i: I) => T.Effect<R, E, A>) {
return (n: I, orig: I) => T.if(() => f(n), constUnit)(n !== orig)
}

const constUnit = constant(T.unit)
18 changes: 17 additions & 1 deletion packages/core/ext/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import {
effectAsyncInterrupt,
fail,
fromEither,
if_,
IO,
succeed,
succeedWith,
tap,
unit,
} from "@effect-ts/core/Effect"
import type * as Ei from "@effect-ts/core/Either"
import * as O from "@effect-ts/core/Option"

import { flow, Lazy, pipe } from "./Function"
import { constant, flow, Lazy, pipe } from "./Function"

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

export function ifDiffR<I, R, E, A>(f: (i: I) => Effect<R, E, A>) {
return (n: I, orig: I) => ifDiff_(n, orig, f)
}

export function ifDiff<I, R, E, A>(n: I, orig: I) {
return (f: (i: I) => Effect<R, E, A>) => ifDiff_(n, orig, f)
}

export function ifDiff_<I, R, E, A>(n: I, orig: I, f: (i: I) => Effect<R, E, A>) {
return if_(n !== orig, () => f(n), constUnit)
}

const constUnit = constant(unit)

export * from "@effect-ts/core/Effect"
16 changes: 16 additions & 0 deletions packages/core/ext/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,19 @@ export function capitalize<T extends string>(string: T): Capitalize<T> {
export function uncapitalize<T extends string>(string: T): Uncapitalize<T> {
return (string.charAt(0).toLowerCase() + string.slice(1)) as Uncapitalize<T>
}

export function tupledCurry<A, B, C>(f: (b: B) => (a: A) => C) {
return (t: [A, B]) => f(t[1])(t[0])
}

export function reverseCurry<A, B, C>(f: (b: B) => (a: A) => C) {
return (a: A) => (b: B) => f(b)(a)
}

export function curry<A, B, C>(f: (a: A, b: B) => C) {
return (b: B) => (a: A) => f(a, b)
}

export function uncurry<A, B, C>(f: (b: B) => (a: A) => C) {
return (a: A, b: B) => f(b)(a)
}
7 changes: 4 additions & 3 deletions packages/types/Task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
reasonableString,
withDefault,
} from "@effect-ts-app/core/ext/Schema"
import { curry, reverseCurry, uncurry } from "@effect-ts-app/core/ext/utils"

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

static addAudit = (audit: TaskAudit) =>
Task.lens["|>"](Lens.prop("auditLog"))["|>"](Lens.modify(A.snoc(audit)))
static addAudit_ = (t: Task, audit: TaskAudit) => Task.addAudit(audit)(t)

static update = (_: OptionalEditableTaskProps) => (t: Task) => Task.update_(t, _)
static addAuditR = reverseCurry(Task.addAudit)
static addAudit_ = uncurry(Task.addAudit)

static update_ = (t: Task, _: OptionalEditableTaskProps) => {
const nt = {
Expand All @@ -119,4 +119,5 @@ export class Task extends Model<Task>()({
}
return nt
}
static update = curry(Task.update_)
}
10 changes: 8 additions & 2 deletions packages/types/Task/audit.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { LazyGetter } from "@effect-ts/core/Utils"
import {
date,
defaultProp,
Expand All @@ -11,6 +12,7 @@ import {
union,
UUID,
} from "@effect-ts-app/core/ext/Schema"
import { reverseCurry } from "@effect-ts-app/core/ext/utils"

import { UserId } from "../ids"
import { Attachment, FileName } from "./shared"
Expand All @@ -34,8 +36,12 @@ export class TaskFileAdded extends Model<TaskFileAdded>()({
...AuditProps("TaskFileAdded"),
fileName: prop(FileName),
}) {
static fromAttachment(a: Attachment) {
return partialConstructor_(TaskFileAdded, { fileName: a.fileName })
static fromAttachmentR = (a: Attachment) =>
partialConstructor_(TaskFileAdded, { fileName: a.fileName })

@LazyGetter()
static get fromAttachment() {
return reverseCurry(TaskFileAdded.fromAttachmentR)
}
}

Expand Down
53 changes: 30 additions & 23 deletions packages/types/User.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as A from "@effect-ts/core/Collections/Immutable/Array"
import * as O from "@effect-ts/core/Option"
import { Option } from "@effect-ts/core/Option"
import { LazyGetter } from "@effect-ts/core/Utils"
import {
array,
date,
defaultProp,
Email,
GetPartialConstructor,
Model,
namedC,
ParsedShapeOf,
Expand All @@ -16,6 +16,7 @@ import {
props,
reasonableString,
} from "@effect-ts-app/core/ext/Schema"
import { reverseCurry, uncurry } from "@effect-ts-app/core/ext/utils"

import { TaskId, UserId } from "./ids"
import { Task } from "./Task"
Expand All @@ -37,32 +38,38 @@ export class User extends Model<User>()({
myDay: defaultProp(array(MyDay)),
phoneNumber: prop(PhoneNumber),
}) {
static createTask__ =
(a: GetPartialConstructor<typeof User["createTask_"]>) => (u: User) =>
User.createTask_(u, a)
@LazyGetter()
static get createTask() {
return reverseCurry(User.createTaskR)
}

static createTask_ = (u: User, a: GetPartialConstructor<typeof User["createTask"]>) =>
User.createTask(u)(a)
static createTask = (u: User) => createPartialTask({ createdBy: u.id })
@LazyGetter()
static get createTask_() {
return uncurry(User.createTask)
}
static createTaskR = (u: User) => createPartialTask({ createdBy: u.id })

static createTaskList__ =
(a: GetPartialConstructor<typeof User["createTaskList_"]>) => (u: User) =>
User.createTaskList_(u, a)
@LazyGetter()
static get createTaskList() {
return reverseCurry(User.createTaskListR)
}

static createTaskList_ = (
u: User,
a: GetPartialConstructor<typeof User["createTaskList"]>
) => User.createTaskList(u)(a)
static createTaskList = (u: User) => createPartialTaskList({ ownerId: u.id })
@LazyGetter()
static get createTaskList_() {
return uncurry(User.createTaskList)
}
static createTaskListR = (u: User) => createPartialTaskList({ ownerId: u.id })

static createTaskListGroup__ =
(a: GetPartialConstructor<typeof User["createTaskListGroup_"]>) => (u: User) =>
User.createTaskListGroup_(u, a)
static createTaskListGroup_ = (
u: User,
a: GetPartialConstructor<typeof User["createTaskListGroup"]>
) => User.createTaskListGroup(u)(a)
static createTaskListGroup = (u: User) =>
@LazyGetter()
static get createTaskListGroup() {
return reverseCurry(User.createTaskListGroupR)
}

@LazyGetter()
static get createTaskListGroup_() {
return uncurry(User.createTaskListGroup)
}
static createTaskListGroupR = (u: User) =>
createPartialTaskListGroup({ ownerId: u.id })

static getMyDay = (t: Task) => (u: User) =>
Expand Down

1 comment on commit 360c404

@vercel
Copy link

@vercel vercel bot commented on 360c404 May 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.