mobily/ts-belt

is reverse-currying considered idiomatic?

Opened this issue · 0 comments

I was making interchangeable Pos and Size, and they work like

Pos(1, 2) + Size(3, 4) // Pos(4, 6)
Size(1, 2) + Pos(3, 4) // Size(4, 6)

but currying didn't work well with pipe (since pipe is data-first), I had to do something like this:

import { pipe } from '@mobily/ts-belt'

type A = { tag: 'A' }
type B = { tag: 'B' }
type Two = A | B

function foo(a: Two): (c: Two) => Two
function foo(a: Two, b: Two): Two
function foo(a: Two, b?: Two) {
  return b ? a : (c: Two) => foo(c, a)
}

const [a, b] = [{ tag: 'A' }, { tag: 'B' }] as const

console.log(foo(a, b)) // { tag: 'A' }
console.log(foo(b)(a)) // { tag: 'B' }
console.log(pipe(a, foo(b))) // { tag: 'A' }

is this considered idiomatic? I see most of ts-belt's (data-first) functions take the same approch, i.e reversed currying, for example S.concat:

function concat(appendValue: string): (str: string) => string
function concat(str: string, appendValue: string): string

however, I'm confused because ts-belt is written in rescript, and in rescript docs about pipe, it says

Do not abuse pipes; they're a means to an end. Inexperienced engineers sometimes shape a library's API to take advantage of the pipe. This is backwards.

does ts-belt take this approach because of pipe's limitation (cannot change position of argument unless using lambda)?

getName(input)
  ->namePerson(personDetails, _)