-
-
Notifications
You must be signed in to change notification settings - Fork 503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
change Writer definition and remove Tuple2 module in favour of Writer #1767
base: 3.0.0
Are you sure you want to change the base?
Conversation
* | ||
* @since 3.0.0 | ||
*/ | ||
export const mapFst: Functor2<URI>['map'] = map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💭 How useful is it really to have these aliases? That made good amount of sense for Tuple2 to be named fst
and snd
for the correlation to a data structure which has a first and second index, but it feels misplaced for Writer
since it's an effect, which just so happens to be encoded as a Tuple2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, however I propose to identify Writer<W, A>
with [A, W]
as a design choice, like TaskEither<E, A>
is Task<Either<E, A>>
as a design choice.
For example I often see people asking: "how can I convert a TaskEither<E, A>
into a Task<Either<E, A>>
?" There's no helper for that in fp-ts
because TaskEither<E, A>
already is Task<Either<E, A>>
by design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a risk that by embracing these implementation details we're making breaking changes hard or even impossible to make.
A problem I've observed in the real world is that IO
, Lazy
, and old () => A
functions are the same to the type system. This issue is somewhat extended to Reader
when you're only touching the output. You'd ideally want a type error when you mistakenly mix these, but at present it's up to the user to notice.
import { pipe } from 'fp-ts/function'
import * as Lazy from 'fp-ts-std/Lazy'
declare const f: Lazy<number>
declare const g: (n: number) => IO<number>
// Hidden side effect at `g`
const x: Lazy<number> = pipe(f, Lazy.chain(g))
This is more broadly an issue with how you can execute effects like IO
and Task
as ordinary nullary function application. This is great for adoption but as a team and codebase scale it starts to become a problem as it obscures where effects are happening.
This can be solved by encoding these types as newtypes, but not if the entire ecosystem relies upon their subtyping relationships.
No description provided.