Skip to content

Conversation

@gcanti
Copy link
Owner

@gcanti gcanti commented Sep 9, 2022

No description provided.

*
* @since 3.0.0
*/
export const mapFst: Functor2<URI>['map'] = map
Copy link

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

Copy link
Owner Author

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.

Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants