Pull to refresh

Comments 18

Функциональное программирование неплохо формирует мышление, является очень выразительным и часто лаконичным решением.

return EitherAsync.liftEither(this.stateManager.checkUserExpiration())
  .bimap(
    // если дата истекла
    () => EitherAsync.liftEither(this.stateManager.getUser())
      .map((user) => user.id)
      .chain((userId) => this.userService.getUser(userId ?? ''))
      .map((user) => this.stateManager.setUser(user)
        .chain(() => this.stateManager.setUserExpiration())
        .reduce((acc) => acc, user))
      .chain((user) => EitherAsync.liftEither(this.stateManager.checkUserStatus())
        .map(() => user)
        .chainLeft(async (statusError) => (await this.authService.removeAllUserSessions(user.id))
          .chain(() => this.stateManager.logout())
          .map(() => statusError),
        ),
      )
      .then((either) => either.extract()),

    // если дата НЕ истекла
    () => this.stateManager.getUser().extract(),
  )
  .run()
  .then((either) => either.extract());

if( !this.user ) return null
if( !this.userIsExpired ) return this.user

this.user = this.userService.get( user.id ?? '' )
this.userSetExpiration()

if( this.userHaveRightStatus() ) return this.user

this.authService.userSessionsClear( user.id )
this.logout()

return null

Занавес.

Нарушена бизнес логика процесса, пропущена пара важных вызовов, не обработаны ошибки, в конце концов даже возвращается не то, что нужно. А в остальном всё нормально! =)

Вот видите, вы в моём коде разобрались с пол пинка, а я ваш до сих пор не понимаю, и ваши загадки не разгадал.

Я ж так и написал:

Функциональное программирование неплохо формирует мышление

)))

Статья для тех, кто интересуется этим вопросом. Вас никто не заставляет их использовать

if( !this.user ) return null

В теории там что-то типа if( !(isPromise(this.user) ? await this.user : this.user) ) return null , и так для каждой строки. Но в практическом смысле таких неопределенностей лучше конечно избегать, если это возможно.

Ну вот видите, в вашем примере тоже с пол пинка не разобраться. Какие тогда претензии к коду автора?)

UFO just landed and posted this here

Кажется вам должна понравиться rxjs :)

так и есть =) но руки до нее пока не дошли

Rxjs не монадический, хотя выглядит похоже. Был проект, который добавляет некоторые алгебраические типы поверх https://gcanti.github.io/fp-ts-rxjs/. Монадический аналог для стримов это https://github.com/cujojs/most, откуда rxjs@5 как мне кажется утянули идею с операторами. Но весь хайп уже давно в прошлом.

нет ли на примете полноценного проекта, написанного на rxjs?

С rxjs ровно те же проблемы, если чуть больше логики попытаетесь на нем делать, императивный код радикально проще.

Дичайше плюсую вашему комментарию.

Я всего лишь хотел подметить, что автору статьи он должен понравиться :)

метод chain, который принимает на вход метод, возвращающий монаду другого типа (назовем его Monad2).

Не-а. Метод chain (aka flatMap или bind) должен возвращать ту же самую монаду: m a -> (a -> m b) -> m b -- согласно определению монады. В общем случае разные монады между собой не композятся. Собственно в этом главная их проблема.

Условно, если вы положили письмо в конверт, а конверт - в почтовый ящик, то уже не сможете достать письмо обратно из ящика без конверта. Ну или вывернуть наизнанку - чтобы письмо оказалось в ящике, а ящик в конверте.

Для каких-то частных случаев можно придумать такой комбинатор монад, но это если вам повезет. Либо руками создать химеры как EitherAsync.

https://github.com/fantasyland/fantasy-land#fantasy-landchain-method

Да, сильно некорректно написал:

chain<L2, R2>(f: (value: R) => Either<L2, R2>): Either<L | L2, R2>;

Тип монады тот же самый, но тип значения новый

Спасибо за замечание!

Если первый пример еще читаемый и делает его читаемым то что массивы имеют схожий функционал, а не использование монад, то второй имхо не читаемый вообще.

Я лично еще не встретил не одного явного плюса в использовании всего этого, кроме пожалуй выучить еще один подход, но для написания чистый функций не обязательно использовать монады(в вашем случае хватит static методов на классах(потому что без typescript это без ошибок не написать) или просто передавать аргументы в функции все зависит от проекта

Sign up to leave a comment.

Articles