Использование монады считывателя в привязке (или преобразователей монады в привязке) - PullRequest
4 голосов
/ 06 февраля 2011

Может кто-нибудь показать, как использовать монаду оснастки внутри монады читателя?Монадные трансформаторы меня смущают.(В качестве альтернативы, я с удовольствием приму предложения учебников о монадных преобразователях, способах увидеть свет и, наконец, уловить их.)

Редактировать: Упс;забыл указать, что я на самом деле пытаюсь сделать, вместо того, чтобы просить помощи с конкретной вещью.Стратегия, а не тактика.Я специально хочу разделить соединение / пул базы данных между всеми обработчиками, без необходимости явно передавать это соединение / пул базы данных при указании маршрутов.Похоже, что для достижения этого была бы монада читателя.

Ответы [ 3 ]

5 голосов
/ 07 февраля 2011

Snap имеет тип ApplicationState, который позволяет упаковать любые необходимые ресурсы приложения (подключения к базе данных, механизмы шаблонов и т. Д.)ApplicationState.Вы можете просто разместить там соединение с БД, и оно будет доступно в любом месте вашего приложения Snap.

4 голосов
/ 07 февраля 2011

Если вы не боитесь использовать расширения, специфичные для GHC, вот простой подход к монадным трансформаторам:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Control.Monad.Reader

data ReaderData = ...

newtype MyMonad a = MyMonad (ReaderT ReaderData Snap a)
  deriving (Monad, MonadReader ReaderData)

runMyMonad :: MyMonad a -> ReaderData -> Snap a
runMyMonad (MyMonad m) r = runReaderT m r

liftSnap :: Snap a -> MyMonad a
liftSnap act = MyMonad (lift act)

Теперь вы можете использовать ask и local для доступа к данным считывателя. Чтобы запустить действие в монаде Snap, вам нужно «поднять» его в вашу новую монаду.

... r <- liftSnap $ ... snap action ...

Вы можете предпочесть более короткое имя. Так что, может быть, просто snap.

0 голосов
/ 07 февраля 2011

Предполагается, что монада привязки имеет значение http://hackage.haskell.org/packages/archive/snap-core/0.4.0/doc/html/Snap-Types.html... Snap - это монада (не преобразователь монад), поэтому вы не можете запустить ее внутри произвольной монады.Вы можете использовать преобразователь ReaderT для встраивания функциональности Reader в Snap, если это именно то, что вам нужно.

Тип runSnap -

runSnap :: Snap a -> (ByteString -> IO ()) -> (Int -> IO ()) -> Request -> Iteratee ByteString IO (Request, Response)

, который говорит нам, что он работает вIteratee ByteString IO монада.Монада Reader не позволяет вам выполнять ввод-вывод или выполнять итерации по входному потоку, поэтому вы не можете выполнять вычисления Snap в монаде Reader.

Если вы объясните, чего хотите достичь, кто-то может предложитьспособ достичь этого.

...