Состояние монады в TypeScript


Вот моя реализация государственной монады в машинописный текст, основана на реализации канонических Хаскелл. Я хочу, чтобы это получить код пересматривается.

class StateMonad<S, A> {
  constructor(public runState: (s: S) => ({ s: S, a: A })) {
  }

  static return_<S, A>(a: A): StateMonad<S, A> {
    return new StateMonad(s => ({ s, a }));
  }

  bind<B>(func: (a: A) => StateMonad<S, B>): StateMonad<S, B> {
    return new StateMonad<S, B>((s: S) => {
      const { s: s_, a } = this.runState(s);
      return func(a).runState(s_);
    });
  }
}

// aux monad factory
const createCounter = (regex: RegExp) => new StateMonad((s: string) =>
  s.split('')
    .reduce((acc, c) =>
      (regex.test(c)) ? { s: acc.s.replace(c, ''), a: acc.a + 1 } : acc,
      { s, a: 0 })
);

const countLowerCase = createCounter(/[a-z]/);
const countDigits = createCounter(/[0-9]/);


// usage example
const { a } = countLowerCase   /* -- haskell equivalent   */
  .bind(n1 => countDigits      /* do n1 <- countLowerCase */
    .bind(n2 => StateMonad     /*    n2 <- countDigits    */
      .return_(n1 + n2)))      /*    return n1 + n2       */
  .runState("abc123ABC");


264
6
задан 5 апреля 2018 в 07:04 Источник Поделиться
Комментарии
1 ответ

Я, наверное, сошел с ума, но что, если вместо вложенной цепи привязать, вы использовали ветвления/соединения типа подход?

static combine<T, S, R>(
monads: { [P in keyof T]: StateMonad<S, T[P]> },
selector: (values: T) => R
)
: StateMonad<S, R> {
return new StateMonad<S, R>((state) => {
var ret: any = {};
for (const key in monads) {
if (monads.hasOwnProperty(key)) {
ret[key] = monads[key].runState(state).a;
}
}
return { a: selector(ret), s: state }
}
);
}

и

var { a } = StateMonad
.combine(
{
countLowerCase,
countDigits
},
combined =>
combined.countLowerCase +
combined.countDigits
)
.runState("abc123ABC");

1
ответ дан 20 июня 2018 в 08:06 Источник Поделиться