Size: a a a

2021 January 28

AP

Aleksei (astynax) Pi... in Haskell Start
$! внутри
источник

к

кана in Haskell Start
ты не туда смотришь, это дефолт
источник

к

кана in Haskell Start
источник

к

кана in Haskell Start
вот для Foldable [] инстанса
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Это примерно то же самое, уж. Тоже foldr с энергичной функцией сворачивания
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Только получше оптимизирована (инлайнится и oneShot lambda использует)
источник

AA

A64m AL256m qn<co... in Haskell Start
ну так никакие аналоги тоже через переписывание нормально не объяснить
источник
2021 January 29

K

Kaksisve in Haskell Start
Товарищи, помогите мне разобраться с монадными трансформерами.

У меня есть трансформер ApiT, который отвечает за соединение с API ВК и обработку ошибок типа ApiError:
newtype ApiT m a = ApiT
   { runApiT :: ReaderT ApiConnection (ExceptT ApiError m) a
   }

Теперь я хочу наслоить на ApiT работу с Long Poll API. Для этого я добавляю StateT LongPollState, но при этом тип обрабатываемых ошибок меняется с ApiError на LongPollError (LongPollError может обернуть ApiError с помощью одного из конструкторов).
Я могу описать это таким образом:
newtype LongPollApiT m a = LongPollApiT
   { runLongPollApiT :: StateT LongPollState (ReaderT ApiConnection (ExceptT LongPollError m)) a
   }
Тогда я могу написать функцию, которая будет lift ить ApiT в LongPollApiT.
Но мне не нравится дублирование кода, т.к. дальше я введу ещё один трансформер, который будет "наслаиваться" на LongPollApiT, точно также дублируя код.

А я хочу писать нечто вроде:
StateT LongPollState (ApiT m) a
Но при этом я хочу гарантировать, что ApiT может кидать только ApiError, а LongPollApiT - LongPollError.

Как мне организовать эту многослойную систему ошибок?
(параметризовывать ApiT типом ошибок не очень хочется, но если это лучший вариант, то я сделаю так)
источник

K

Kaksisve in Haskell Start
Поможет ли здесь withExceptT?
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Параметризуйте тип ошибки
источник

K

Kaksisve in Haskell Start
Ок, спасибо.
источник

AP

Aleksei (astynax) Pi... in Haskell Start
newtype ApiT e m a = ... ExceptT e m
type SimpleApi = ApiT ApiError
источник

AP

Aleksei (astynax) Pi... in Haskell Start
А зачем вы заворачиваете всё заново в longpollapi?
источник

AP

Aleksei (astynax) Pi... in Haskell Start
type LongPollApiT m = ApiT LongPollError (StateT LongPollState m)
?
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Или вам нужно сохранять состояние между ошибками?
источник

K

Kaksisve in Haskell Start
Aleksei (astynax) Pirogov
А зачем вы заворачиваете всё заново в longpollapi?
Чтобы бот работал, нужно подключиться к LongPoll, а для этого нужно иметь подключение к API.
BotT -> LongPollT -> ApiT

Мне кажется это верным.
источник

K

Kaksisve in Haskell Start
Aleksei (astynax) Pirogov
type LongPollApiT m = ApiT LongPollError (StateT LongPollState m)
?
Почему вы StateT поместили внутрь, а не снаружи?
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Потому что ApiT уже трансформер
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Можно его использовать не только для IO
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Разница между Except(State) и State(Except) в том, что в первом случае конечное состояние доступно, даже если была ошибка, во втором же — "откатывается" (теряется)
источник