fp-ts: Suggestions for breaking changes for next release

This issue tracks suggestions with breaking changes to be included in the next release.

  • Ordering: replace string literal union with numeric enum
//now 
type Ordering = 'LT' | 'EQ' | 'GT';
//changes to
enum Ordering = {
  LT = -1,
  EQ = 0,
  GT = 1
}

This removes the need to manually convert ordering values when using in native comparators.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 36 (19 by maintainers)

Most upvoted comments

I’m quite excited. The new encoding (*) is pretty verbose but

  • type safety is sensibly improved
  • I found a way to re-enable strict function type checks on type classes members

(*) https://github.com/gcanti/fp-ts/blob/1449506613c7d19e0d88023dc93ff6c34ffdeba4/src/Functor.ts#L10-L33

Proposal: add a never default value

Agree, I always do the same if I need to force explicit type argument

@raveclassic so this is my broad agenda

  • I’m working on a 1.0.0 branch right now (if anyone want to follow the progress)
  • when ready (and of course after some discussions) I’ll release a 1.0.0-rc version in the next channel

BUT

I’m eager to experiment with these 2 new features

As soon as they will be merged on master and will be available on typescript@next, I’ll do some experiments to see if I can come up with a better encoding of HKTs (in the working branch is improved but there’s an annoying explosion of interfaces).

If that’s the case, I would postpone the breaking change release (unless we want to tolerate 2 breaking change versions in a row)

Anothe proposal: swap arguments of Functor, Chain (maybe others)

from

export interface Chain<F> extends Apply<F> {
  chain<A, B>(f: (a: A) => HKT<F, B>, fa: HKT<F, A>): HKT<F, B>
}

to

export interface Chain<F> extends Apply<F> {
  chain<A, B>(fa: HKT<F, A>, f: (a: A) => HKT<F, B>): HKT<F, B>
}

Why?

  1. more readable
const chain2 = <A, B>(fa: Option<A>, f: (a: A) => Option<B>): Option<B> => {
  return fa.chain(f)
}

declare const fa: Option<string>
declare const f: (s: string) => Option<string>
declare const g: (s: string) => Option<string>
declare const h: (s: string) => Option<string>

// from
chain(a => chain(b => chain(h, g(b)), f(a)), fa) // <- fa is in last position

// to
chain2(fa, a => chain2(f(a), b => chain2(g(b), h)))
//      ^ fa is in first position
  1. better suggestions while writing
declare const fa: Option<string>

const x = chain(a => some(a.)) // no suggestions

const y = chain2(fa, a => some(a.)) // suggestions (substring, etc...)

Here’s my list so far

  • drop Flow support
  • remove toOption in Either (now deprecated)
  • remove monoidArray and semigroupArray (now deprecated)

Since funxfix already does that, I’m ok with the L convention

Most notable change: instance members are no more exported as top level functions so instead of

import * as option from 'fp-ts/lib/Option'

const x: option.Option<whatever> = option.map(...)

you must write

import { Option, option } from 'fp-ts/lib/Option'

const x: Option<whatever> = option.map(...)

@raveclassic I would change to

export type Ordering = -1 | 0 | 1

instead, enums look unsafe

enum Ordering {
  LT = -1,
  EQ = 0,
  GT = 1
}

declare function f(o: Ordering): void

f(1000) // WAT

@raveclassic yeah, it has been a very nice experiment (Flow is great with respect to type inference and HKT support) but I’m not a Flow user and my professional interest is pretty low. After some weeks of maintenance I think it doesn’t worth to keep the definition files here, there’s flow-typed for that

Another one:

  • rename all phantom fields using dashes
class Some<A> {
-  // prettier-ignore
-  readonly '_A': A
+  readonly '-A': A
}

no prettier comments required and (AFAIK) they don’t show up in quick info