DEV Community

Discussion on: Getting started with fp-ts: Reader

Collapse
 
massimilianorango profile image
massimilianorango

Wow, this looks great! 😍
I'm having trouble understanding how the Reader monad can help in more complex examples though.
Take a look at this for instance: (functions with the "2" suffix are the ones that I would write having dependencies as the first parameter)

export interface Dependencies {
  readonly i18n: {
    readonly true: string
    readonly false: string
  }
  readonly lowerBound: number
}

export interface OtherDependencies {
  readonly semicolon: boolean
}

// Transform:
const transform = (a: string) => (deps: OtherDependencies) =>
  `myString${deps.semicolon ? ':' : ''} ${a}`

const transform2 = (deps: OtherDependencies) => (a: string) =>
  `myString${deps.semicolon ? ':' : ''} ${a}`

// AnotherTransform:
const anotherTransform = (a: string) => (deps: OtherDependencies) =>
  `${a}${deps.semicolon ? ':' : ''} myString`

const anotherTransform2 = (deps: OtherDependencies) => (a: string) =>
  `${a}${deps.semicolon ? ':' : ''} myString`

// F:
const f = (b: boolean) => (deps: Dependencies) =>
  pipe(
    b,
    ifElse(equals(true), always(deps.i18n.true), always(deps.i18n.false))
  )

const f2 = (deps: Dependencies) =>
  ifElse(equals(true), always(deps.i18n.true), always(deps.i18n.false))

// G:
const g = (n: number) => (deps: Dependencies & OtherDependencies) =>
  pipe(
    n > 2,
    f,
    ff => ff(deps),
    s => transform(s)(deps),
    s => anotherTransform(s)(deps)
  )

const g2 = (deps: Dependencies & OtherDependencies) =>
  flow(
    (n: number) => n > 2,
    f2(deps),
    transform2(deps),
    anotherTransform2(deps)
  )
Enter fullscreen mode Exit fullscreen mode

In particular, notice how:

  1. f needs to make b explicit even if could be implicit (like it is in f2)
  2. all the functions in the g pipe need to take the result from the previous computation and pass it as the first parameter to the transform functions, while this is implicit in g2. This leads to less readable code and harder composition. Is there something I'm missing?
  3. Is it generally right to merge all the dependencies of the functions used by g like I did with Dependencies & OtherDependencies?
Collapse
 
gcanti profile image
Giulio Canti
import { pipe } from 'fp-ts/lib/pipeable' // v2.6
import { chainW, Reader } from 'fp-ts/lib/Reader'

export interface Dependencies {
  readonly i18n: {
    readonly true: string
    readonly false: string
  }
  readonly lowerBound: number
}

export interface OtherDependencies {
  readonly semicolon: boolean
}

declare function transform(a: string): Reader<OtherDependencies, string>
declare function anotherTransform(a: string): Reader<OtherDependencies, string>
declare function f(b: boolean): Reader<Dependencies, string>

const g = (n: number) => pipe(f(n > 2), chainW(transform), chainW(anotherTransform))
Collapse
 
massimilianorango profile image
massimilianorango

That's exactly what I needed. I saw you just released chainW in 2.6.0. Great job thanks! :)