samhh / fp-ts-std

The missing pseudo-standard library for fp-ts.
https://samhh.github.io/fp-ts-std/
MIT License
207 stars 27 forks source link

runReader #132

Closed samhh closed 2 years ago

samhh commented 2 years ago

Alias of apply.

https://hackage.haskell.org/package/transformers-0.6.0.4/docs/Control-Monad-Trans-Reader.html#v:runReader

stefanoCrmg commented 2 years ago

Is this what you'd expect?

export const runReader: <R, A>(r: R) => (reader: Reader<R, A>) => A =
  (r) => (reader) =>
    reader(r)

If I were to write it just like the Haskell implementation I think it would likely be a bit annoying to use in a pipe e.g with my proposed solution you could

type Env = { env: string }
declare const myReader: RTE.ReaderTaskEither<Env, Error, string>

const getString: TE.TaskEither<Error, string> = pipe(
  myReader,
  runReader({env: 'hello'})
)

But if I were to reverse the order of r and reader to be closer to the Haskell's signature you'd end up having to do something like

type Env = { env: string }
declare const myReader: RTE.ReaderTaskEither<Env, Error, string>

const getString: TE.TaskEither<Error, string> = pipe(
  myReader,
  _ => runReader(_)({env: 'hello'})
)

I don't really know much about of Haskell so I'm sorry if I understood the signature incorrectly.

Also, wouldn't it also make sense to introduce a runReaderTask function that would runrunReader as well as Task.execute? 😄

samhh commented 2 years ago

That first runReader is it, although r => reader => reader(r) could be replaced with apply. The purpose is to provide a centralised way to run a reader that hides the implementation detail that it's just a function.

Yep, per-monad transformer variants make sense. I wouldn't run execute though, that's really for the very edges of the application. Example:

declare const runReaderTask: <R>(r: R) => <A>(m: ReaderTask<R, A>) => Task<A>

That could probably also be just apply.