#api #haskell #monad-transformers
#API #haskell #монады-трансформеры
Вопрос:
Просто думаю о дизайне API. Что является «общим» в Haskell? Трансформаторы в подписи типа или, скорее, «скрытые»?
findById :: ID -> IO (Maybe User)
findById x = runMaybeT $ do
...
return User
или
findById :: ID -> MaybeT IO User
findById x = do
...
return User
Комментарии:
1. Третья альтернатива для рассмотрения: одна из
(MonadIO m, Alternative m) => ID -> m User
, если действительно нет интересной информации об ошибках, которую вы можете сообщить, или(MonadIO m, MonadError MyFancyError m) => ID -> m User
если есть.
Ответ №1:
Если это для чего-то простого, и это всего лишь несколько функций, которые делают это, возможно, в IO, я бы просто создал тип IO (Maybe User)
.
Если это шаблон, который распространяется по всей вашей библиотеке, я бы дал полуабстрактное имя монаде tfm-stack:
type Request = MaybeT IO
findById :: ID -> Request User
… или даже
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Request a = Request (runRequest :: MaybeT IO a)
deriving (Functor, Applicative, Monad)
Создание подписи ID -> MaybeT IO User
не очень хорошо: трансформатор помогает только в том случае, если вы выполняете целую кучу действий в этой монаде, но в этом случае всегда запись MaybeT IO
нарушает принцип DRY.
Комментарии:
1. ради интереса,
findById
будет ли тогда выглядетьfindById :: ID -> Request User n findById 1 = return User n findById _ = Request . MaybeT $ return Nothing
правильно?2. Да. Если вы также производите
Alternative
, вы можете упростить случай сбоя доfindById _ = empty
.