2012-01-27 23 views
13

Bawię się pisząc aplikację internetową. W tym przypadku używam scotty i redis, ale ten problem pojawia się w dowolnej kombinacji web/db. Przedtem korzystałem z pakietu happstack, więc bardzo bym tam podoba.Połączyć dwie monady, gdy nie ma transformatora?

Scotty ma definiować trasy w zagnieżdżonych monady, co sprawia, że ​​łatwo uzyskać dostęp do połączenia z bazą danych w obrębie szlaku:

main = do 
    db <- connect defaultConnectInfo 
    scotty 3000 $ do 

    get "/keys" $ do 
     keys <- liftIO $ runRedis db $ keys "*" 
     html $ T.pack $ show keys 

blokują Get ma typ: Web.Scotty.ActionM(). Wszystkie polecenia redis mają typ Database.Redis.Redis a. Ani redis, ani scotty nie mają transformatora monadowego.

Jaki jest najlepszy sposób na połączenie tych elementów? Jestem nowy w firmie haskell, ale udało mi się przekonać program ReaderT do pracy z monadą internetową w aplikacji happstack.

Idealnie, mógłbym jakoś stworzyć nowy stos monady, który obsługuje zarówno keys, jak i html w tym samym bloku.

+1

Czy ludzie zwykle decydują się na liftIO w sieciach internetowych haskell? –

+1

Nie znam odpowiedzi tutaj, ale sądzę, że twój problem jest podobny do transformatorów Monady. Zasadniczo chcesz zaimplementować typ, nazwijmy go 'IdentityTT m 'ma', tak aby' IdentityTT m'' zachowywał się dokładnie jak ['IdentityT'] (http://hackage.haskell.org/packages/archive/transformers /0.2.1.0/doc/html/Control-Monad-Trans-Identity.html). Pierwszym pytaniem, na które należy udzielić odpowiedzi, jest oczywiście to, czy jest to możliwe. –

+0

Innym sposobem na wyrażenie pytania jest: Czy używasz liftIO do wysyłania zapytań do bazy danych we wszystkich frameworkach haskell? Jaki jest najczęstszy wzorzec, gdy baza danych nie jest upieczona do struktury? –

Odpowiedz

4

Z jakiegoś powodu wydawało mi się, że liftIO było brzydkie, ale to naprawdę nie jest złe. Zwłaszcza jeśli to zrobić:

queryRedis :: Connection -> Redis a -> ActionM a 
queryRedis db r = liftIO $ runRedis db r 

i zdefiniować funkcję redis = queryRedis db częściowo stosowana. Dziękuję wszystkim