How to dispatch one argument to multiple function in fp-ts

Viewed 673

I have the following code

export const getPostData = (id: string) =>
  pipe(
    getFullPathFileNameForPosts(`${id}.md`), // IO<string>
    chain(getFileContents), // IO<string>
    chain(getMatter), // IO<matter.GrayMatterFile<string>>
    map(R.pick(['data'])),
    bind('id', () => () => id)
  );

above function getPostData() retun

IO<{
  data: {[key: string]: any};
  id: string;
}>

Now I have to add some fileds in the returned result, let's say content, and the result looks like

IO<{
  data: {[key: string]: any};
  id: string;
  content: string;
}>

I write a new function getContent = (matter: matter.GrayMatterFile<string>) => {...}, Now how to add this function to the combined function getPostData?

The main question I want to ask is how to divide the values into different functions for processing in the combined function.

Because the getFileContents function in chain(getFileContents) needs to read the file, I don't want to read this file twice

1 Answers

You can keep using bind and bindTo to keep all the values you need around until you are done using them.

Since you need a matter.GrayMatterFile as an input for the getContent function, you will need to "keep" that value around for a bit longer.

Here is one possible approach:

import { pipe} from 'fp-ts/lib/function'
import { chain, map, bind, bindTo, IO, of } from 'fp-ts/lib/IO'
import { GrayMatterFile } from 'gray-matter'

declare const getMatter: (fileContents: string) => IO<GrayMatterFile<string>>

declare const getFileContents: (filepath: string) => IO<string>

declare const getFullPathFileNameForPosts: (filename: string) => IO<string>

declare const getContent: (file: GrayMatterFile<string>) => IO<string>

export const getPostData = (id: string) =>
  pipe(
    getFullPathFileNameForPosts(`${id}.md`), // IO<string>
    chain(getFileContents), // IO<string>
    chain(getMatter), // IO<matter.GrayMatterFile<string>>
    bindTo('grayMatterFile'),
    bind('content', ({ grayMatterFile }) => getContent(grayMatterFile)),
    map(({ content, grayMatterFile }) => ({
      content: content,
      data: grayMatterFile.data,
      id
    })),
  );
Related