-
-
Notifications
You must be signed in to change notification settings - Fork 501
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
What's your monad stack? #251
Comments
I'm only in the middle of integration of fp-ts into our codebase. We are using Option, Either and some custom ADTs right now. The plans are to use Validation also. |
@raveclassic I mean when you have to nest monads, let me show you an example. Say you have a simple API like this import { Task } from 'fp-ts/lib/Task'
import axios from 'axios'
/** If successful, returns the invoice id */
const purchase1 = (userId: string, productId: string): Task<string> =>
new Task(() => axios.post(`https://mysite/api/user/${userId}/purchase/${productId}`, {}).then(res => res.data)) There's no error handling though, so you switch to type PurchaseError = { type: 'UserNotFound' } | { type: 'ProductNotFound' } | { type: 'PurchaseNotAllowed' }
import { TaskEither, tryCatch } from 'fp-ts/lib/TaskEither'
const purchase2 = (userId: string, productId: string): TaskEither<PurchaseError, string> =>
tryCatch<PurchaseError, string>(
() => axios.post(`https://mysite/api/user/${userId}/purchase/${productId}`, {}).then(res => res.data),
reason => {
// error handling here...
return { type: 'PurchaseNotAllowed' }
}
) The url is hard-coded though, and here it comes class ReaderTaskEither<E, L, A> {
constructor(readonly run: (e: E) => TaskEither<L, A>) {}
/* ... */
}
type AppConfig = {
apiRoot: string
}
const purchase3 = (userId: string, productId: string): ReaderTaskEither<AppConfig, PurchaseError, string> =>
new ReaderTaskEither(config =>
tryCatch<PurchaseError, string>(
() => axios.post(`${config.apiRoot}/user/${userId}/purchase/${productId}`, {}).then(res => res.data),
// ^ no more hard-coded
reason => {
// error handling here...
return { type: 'PurchaseNotAllowed' }
}
)
)
purchase3('123', '456')
.run({ apiRoot: 'https://mysite/api' })
.value.run()
.then(e => e.fold(error => console.error(error), invoiceId => console.log(invoiceId))) |
A reference implementation ReaderTaskEither |
That s an interesting question and to be honnest, i ve not introduced yet monad transformers to the team. |
@sledorze that's interesting and something I would like to dig deeper into, could you please point me to some resources?
Not sure, that's interesting as well. I'll do some experiments and open a new issue |
@gcanti you may find some insight on his creator (alex) blog: https://alexn.org/blog/2017/10/11/javascript-promise-leaks-memory.html
About performance you can get some infos from here (execution strategies): That may be a good start. |
@gcanti Ok I'm starting to use a stack based on futureEither and readerFutureEither (Future from |
@sledorze really glad to hear that: I tried to build fp-ts so it can be expanded, as I did with fp-ts-fluture or fp-ts-rxjs, your move to funfix is a good proof of that
Maybe you could publish a package |
But since, ReaderTaskEither implements Monad3, we can't use it in the MTL example. Is there any workaround for this? @gcanti |
@RPallas92 with more overloadings (alas doing MTL-style in TypeScript is super verbose) see #410 |
I wonder if it's worth consolidating a common stack, something like
The text was updated successfully, but these errors were encountered: