gcanti / fp-ts

Functional programming in TypeScript
https://gcanti.github.io/fp-ts/
MIT License
10.67k stars 504 forks source link

Fantasy Land support, global HKT functions #1314

Open nythrox opened 3 years ago

nythrox commented 3 years ago

🚀 Feature request

Is it possible to have support for both fantasy-land and static land? This way it would be possible to have "global" functions (like map, that would work on all functors) making using module namespaces optional, and it would also be possible to use fp-ts in a non-pointfree way. This would also allow us to use the generator* do-notation more easily.

Current Behavior

Currently it's only possible to operate on ADTs by importing the namespace-specific functions, and this can ruin the readability of the code. It's also not possible to use fp-ts with methods, that can sometimes be helpfull.

flow(
  O.map((n: number) => n * 2),
  O.chain(n => (n === 0 ? O.none : O.some(1 / n))),
  O.filter(n => n > 1),
  O.fold(() => 'ko', () => 'ok')
)(O.some(1))

Desired Behavior

It would be nice to have support for both pointless and class methods, and this would allow a lot of different possibilities.

Global functions that work on all HKTs

import { map, chain, fold } from "fp-ts" 
flow(
  map((n: number) => n * 2),
  chain(n => (n === 0 ? O.none : O.some(1 / n))),
  filter(n => n > 1),
  fold(() => 'ko', () => 'ok')
)(O.some(1))

Use either pointfree or methods

O.some(1)
.map(n => n * 2)
.chain(n => (n === 0 ? O.none : O.some(1 / n)))
.filter(n => n > 1)
.fold(() => 'ko', () => 'ok')

Possibility of do* notation on all supported ADTs

do(function*() {
    const num = yield* O.some(1) // number
    if (num == 0) {
       yield* O.none
    }
    const oneByN = 1 / n
    if (oneByN > 1) {
       yield* O.none
    }
    return oneByN
}).fold(
  () => 'ko',
  () => 'ok'
)

Suggested Solution

All ADTs that are constructed by constructors will also come with their module methods. Types that are not constructed by the constructor will still be able to be used normally with module functions.

Who does this impact? Who is this for?

This will help codebases look much cleaner with global functions, and also help beginners to understand better the code.

Describe alternatives you've considered

No other typescript libraries have these features currently, but I think fp-ts could support this with its implementation of HKTs, and maybe using varadic tuples to better express generic types.

mikearnaldi commented 3 years ago

Fantasy Land support has been removed for good in v2.0, the discussion is here: https://github.com/gcanti/fp-ts/issues/823

fredericrous commented 4 months ago

To try to give more context, here is another discussion about fantasy-land compatibility https://github.com/gcanti/fp-ts/issues/204 what I understand after a quick read is that it's hard and not worth it to implement in Typescript.

To be more precise, and correct me if I'm wrong, Typescript would need to implement Higher Kinded Type. And this day may never come https://github.com/microsoft/TypeScript/issues/1213 I'm not smart enough to investigate if fp-ts implem of HKT would be enough tho

loads of messages in these discussions, hard to follow and understand all