Fp-ts: HKT as a spec and independent distribution

Created on 5 Jul 2018  路  6Comments  路  Source: gcanti/fp-ts

One problem wit the HKT pattern is that current it looks like it relies on including this library even for a small library--and its kind of obscure that way.

For example, rather than reference this project

https://github.com/devex-web-frontend/remote-data-ts/blob/261680d125176ebf021e6d209171a3e7c490897f/src/remote-data.ts#L24

This project should reference some standard endpoint. Some standardize way of naming a ADT by an author, ie 'babakness/functor'.

Maybe it could just be a standalone hkt library

so instead of this

declare module 'fp-ts/lib/HKT' {
    interface URI2HKT2<L, A> {
        RemoteData: RemoteData<L, A>;
    }
}

its

declare module 'hkt' {
    interface URI2HKT2<L, A> {
        'devex-web-frontend/RemoteData': RemoteData<L, A>;
    }
}

I'm currently working on a library and it doesn't make sense to include this entire library for just one ADT. I feel it should be small dedicated and independent library. Maybe this is something for Fantasyland or perhaps @gcanti can make that repo?

BTW, regarding a closed issue, I'm adding a fold method to my ADT for compatibility here and a reduce for compatibility with Fantasyland, but honestly it would be great if it was just a single standard.

Kudos on some great pioneering work with this library.

suggestion

Most helpful comment

Yeah, I was also thinking about that... It reminds me https://github.com/benlesh/symbol-observable as a single point of interop between libs.

As a downside there would be too many repos to maintain (there already are - fp-ts, typelevel-ts, monocle-ts, io-ts etc). However there's a great solution which I'd _really_ like to adopt here - turn this repo to monorepo (using lerna or yarn namespaces) . Also all libs could be moved to an npm namespace: @fp-ts/hkt, @fp-ts/typeclasses, @fp-ts/adt and so on. There still could be a full-blown package including everything like @fp-ts/platform.

Would really like to hear @gcanti opinion on that.

All 6 comments

Yeah, I was also thinking about that... It reminds me https://github.com/benlesh/symbol-observable as a single point of interop between libs.

As a downside there would be too many repos to maintain (there already are - fp-ts, typelevel-ts, monocle-ts, io-ts etc). However there's a great solution which I'd _really_ like to adopt here - turn this repo to monorepo (using lerna or yarn namespaces) . Also all libs could be moved to an npm namespace: @fp-ts/hkt, @fp-ts/typeclasses, @fp-ts/adt and so on. There still could be a full-blown package including everything like @fp-ts/platform.

Would really like to hear @gcanti opinion on that.

Certainly fp-ts could be split into several packages, what's the benefit though? You can import only what you need (HKT, Semigroup, Monad...) and since they are all just types your bundle doesn't bloat.

@gcanti I believe a valid reason is that types are compiled away, if I wanted to include Monad I also get a flatten function in the library.

I agree with @raveclassic, this is a great idea. My only reservation is that some of the conventions just don't match up with other standards--so maybe it is an independent standard. Yet this is a discussion separate from the simplest one--hkt as simply a common reference point.

For illustration, I have a universal filter function that takes some Filterable type; but Array does not implement partitionMap. So my function can't work on Arrays as they aren't Filterable given this definition:

https://github.com/gcanti/fp-ts/blob/c3ef83e00c068a502109680da2e1041441118dc5/src/Filterable.ts#L23

export interface Filterable<F> extends Functor<F>, Compactable<F> {
  /**
   * Partition a data structure based on an either predicate.
   */
  readonly partitionMap: <RL, RR, A>(fa: HKT<F, A>, f: (a: A) => Either<RL, RR>) => Separated<HKT<F, RL>, HKT<F, RR>>
  /**
   * Partition a data structure based on a boolean predicate.
   */
  readonly partition: <A>(fa: HKT<F, A>, p: Predicate<A>) => Separated<HKT<F, A>, HKT<F, A>>
  /**
   * Map over a data structure and filter based on an option predicate.
   */
  readonly filterMap: <A, B>(fa: HKT<F, A>, f: (a: A) => Option<B>) => HKT<F, B>
  /**
   * Filter a data structure based on a boolean predicate.
   */
  readonly filter: <A>(fa: HKT<F, A>, p: Predicate<A>) => HKT<F, A>
}

So I may define a Filterable as simply a Functor having a filter interface. I will still want to do this

declare module 'hkt' {
  export interface URI2HKT<A> {
   'babakness/filterable': Filterable<A>
  }
}

I also get a flatten function in the library

@babakness No you don't, that's the point of my previous comment: when compiling TypeScript is able to understand that you are just importing the type Monad and won't add any runtime dependency to your code

@babakness Well, I can't think of any other compelling reason to split but to keep things clean and separated. In fact everything is already "split" to separate almost independent modules and @gcanti is right, TS does not include runtime stuff if you import only types. Also I think it's a job for a bundler like webpack or rollup to do dead-code elimination.

Also as a sidenote, Array actually fully implements Filterable: https://github.com/gcanti/fp-ts/blob/c3ef83e00c068a502109680da2e1041441118dc5/src/Array.ts#L857

FYI, just wanted to link to #547, which may be relevant to this issue 馃檪

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Crashthatch picture Crashthatch  路  4Comments

mmkal picture mmkal  路  3Comments

mustafaekim picture mustafaekim  路  4Comments

steida picture steida  路  4Comments

vicrac picture vicrac  路  4Comments