gcanti / monocle-ts

Functional optics: a (partial) porting of Scala monocle
https://gcanti.github.io/monocle-ts/
MIT License
1.05k stars 52 forks source link

`modifyF ` for `Lens`/`Optional`/`Ix`/ ... #149

Closed jituanlin closed 3 years ago

jituanlin commented 3 years ago

For now, monocle-ts only support modifyF in Traversal(even in v3.0.0 branch).

But modifyF is required to make modify context, for example: implementation:

import * as M from 'monocle-ts';
import * as F from 'fp-ts';

export const modifyF4Lens = <F extends F.hkt.URIS>(
  functor: F.functor.Functor1<F>
) => <A>(f: (a: A) => F.hkt.Kind<F, A>) => <S>(lens: M.Lens<S, A>) => (
  s: S
): F.hkt.Kind<F, S> => {
  return F.function.pipe(lens.get(s), f, fa =>
    functor.map(fa, (a: A) => lens.set(a)(s))
  );
};

testing:

import * as F from 'fp-ts';
import * as M from 'monocle-ts';
import {modifyF4Lens} from './index';

describe('modify f', () => {
  test('modifyF in Lens', () => {
    interface Account {
      name: string;
    }

    const nameM: M.Lens<Account, string> = M.Lens.fromProp<Account>()('name');
    const nameModified = modifyF4Lens(F.option.Functor)(name =>
      F.option.some(`${name}Modified`)
    )(nameM)({name: 'monocle'});

    expect(nameModified).toEqual(F.option.some({name: 'monocleModified'}));
  });
});
gcanti commented 3 years ago

@jituanlin I will add modifyF to the experimental modules