mobily / ts-belt

🔧 Fast, modern, and practical utility library for FP in TypeScript.
https://mobily.github.io/ts-belt
MIT License
1.11k stars 31 forks source link

Value first pipe #17

Closed flauwekeul closed 2 years ago

flauwekeul commented 2 years ago

Hi! I'm confused about pipe accepting a value first. Unless I'm missing something, you can't create a point-free (tacit) function.

With a pipe that takes the value last (as in most, if not all implementations), you can do this:

const someFn = pipe(fnA, fnB, fnC)
// later:
someFn(value)

I think this is very clean. With a pipe that takes the value as it's first argument, you always have to "wrap" the composition in a function:

const someFn = (value) => pipe(value, fnA, fnB, fnC)
// later:
someFn(value)

Making a point-free style impossible. Am I missing something?

mobily commented 2 years ago

Unless I'm missing something

no, you’re actually not missing anything :)

I think this is very clean.

I take your point and fully agree this is a very clean solution, but on the other hand most of the time it requires defining types manually, which is not developer-friendly and was much problematic in Ramda (if you use Ramda in TS), and basically I wanted to avoid this, for instance:

type SomeType1 = {
  readonly prop: string
}

const someFn: (arg: SomeType1) => string = createPipe(D.getUnsafe('prop'), S.toUpperCase)

someFn(value)

with the current implementation, you only need to define a type to the provided argument and a result type is correctly inferred:

type SomeType1 = {
  readonly prop: string
}

const someFn = (value: SomeType1) => pipe(value, D.getUnsafe('prop'), S.toUpperCase)

someFn(value)

I consider adding pipe that returns a new function and accepts a single argument but still, due to TS limitations, most of the time developers will have to use it like the following to get types correctly inferred:

const value =  pipe(
  ['hello', 'world'], 
  A.map(createPipe(S.remove('o'), S.toUpperCase)),
) // → ['HELL', 'WRLD']
flauwekeul commented 2 years ago

Thanks for explaining. I didn't take into account that TS is the limiting factor here. Also, I see that fp-ts' pipe has the same signature, probably for the same reason. However, fp-ts also has the flow util. I haven't used it yet, but maybe they figured out a way to make it infer types without too much hassle.

mobily commented 2 years ago

thanks for sharing the link! ❤️ good news, the initial implementation of flow in ts-belt looks really promising, and I think it will be included in the next version

mobily commented 2 years ago

@flauwekeul added and published in v3.6.0 🚀