Допустим, мы хотим использовать ReaderT [(a,b)]
вместо монады Maybe
, а затем мы хотим выполнить поиск в списке.
Теперь простой и не слишком необычный способ:
первая возможность
find a = ReaderT (lookup a)
Однако похоже, что это говорит о некоторых нетривиальных вещах о том, как работает преобразователь ReaderT. Глядя на исходный код Control.Monad.Reader, становится ясно, что это работает просто отлично. Но я не читал никакой документации, подтверждающей это. Однако мы могли бы также написать find следующим образом:
второй вариант
find a = do y <- ask
lift (lookup a y)
Аналогичные идеи применимы для упаковки MaybeT
, StateT
, State
и Reader
. Обычно я пишу что-то вроде первого примера, но в большинстве случаев действительно очевидно, как написать это как второй пример, и вы даже можете сказать, что это более читабельно. Итак, мой вопрос: следует ли считать код, подобный первому примеру, плохим?
find a = lift . lookup a =<< ask
, что так же понятно (ИМХО), как и второй вариант, но короче. - person Antal Spector-Zabusky   schedule 30.11.2010newtype State s a = State {runState :: s -> (a, s)}
(версия 1.1.1), а скорееtype State s = StateT s Identity
(версия 2.0.0). Я не вижу ничего плохого в изменении API таким образом, и на самом деле все могло бы измениться, чтобы сломать любой хорошо написанный код, планирование такой совместимости заранее кажется глупым, но я действительно думаю, что конструкторы меняются с большей вероятностью, чемask
. Почти бессмысленно, но все же актуально =D. - person HaskellElephant   schedule 04.12.2010RULES
прагмах превратить код, подобный приведенному выше, в более приятный способ. - person fuz   schedule 04.12.2010