fp-ts/optic

Pipeable API like monocle-ts@experimental? (plus nice bits from effect)

Closed this issue ยท 3 comments

๐Ÿš€ Feature request

Current Behavior

The optics in this package are class- and method-based, as opposed to the experimental monocle-ts and the rest of effect, which is all function-based.

Desired Behavior

Add pipeable functions to the API, like monocle-ts@experimental. Extra nice things from effect to have:

  1. Pipe method on optics
  2. Overloaded data-first and data-last dual API

Suggested Solution

Repeating myself a bit, but... basically, new package entrypoint exporting pipeable functions.

Who does this impact? Who is this for?

Functional programmers, people using effect, people who want more flexibility in how the functions can be used.

Describe alternatives you've considered

Can obviously just use optics as they are, but the experience is not as good as with pipeable and dual APIs.

Additional context

Methods aren't tree-shakeable or minifiable, functions are.

Your environment

Software Version(s)
@fp-ts/optic 0.24.0
TypeScript 5.4

The idea is to make a mix to provide a better developer experience, meaning to use pipeable functions by default with some notable exceptions that are also encoded as methods. The exceptions are only those that you already see defined as methods now.

Thanks, I'm looking more closely now and can see what you mean.

Still, I really miss the dual API, especially on functions with arity > 2, which are awkward to use with the chained )( calls. I find the effect dual way of doing it to reduce piped nesting.

For example, with the modify function,

export const modify: {
  <S, T, A, B>(optic: PolyOptional<S, T, A, B>, f: (a: A) => B): (s: S) => T
  <S, T, A, B>(s: S, optic: PolyOptional<S, T, A, B>, f: (a: A) => B): T
}

Unfortunately it would be a breaking change but I'd love to hear what you think.

In effect, we're talking about "dual" for a pair of functions with this form:

(...args) => (self) => return
(self, ...args) => return

In this package, technically speaking, it seems to me that there isn't any function that can be effectively made "dual" in the sense I mentioned above. However, this doesn't mean that we can't define overloads to make these APIs more ergonomic.