【问题标题】:Yesod: how to send Redis results as JSONYesod:如何以 JSON 格式发送 Redis 结果
【发布时间】:2013-04-17 23:02:49
【问题描述】:

对于我的 Haskell 经验不足,请提前道歉。我正在为一个学习项目的 Redis 实例编写一个小包装器。到目前为止,Yesod 绝对是一个奇迹。在很少有 Haskell 经验的情况下,我的 browserId Auth 工作正常,并且我成功且快速地将记录插入 Redis。

我一直在弄清楚如何将 Redis 响应转换为 JSON 并发回。这是一个工作的、非脚手架的应用程序,它显示了获取静态 RepJson 或带有 Redis 信息的 RepPlain(应用程序称为 LRedis):

{-# LANGUAGE OverloadedStrings, TemplateHaskell, TypeFamilies,
             MultiParamTypeClasses, QuasiQuotes #-}

import Yesod
import Data.Text
import Data.Text.Encoding
import Data.ByteString.UTF8
import Database.Redis
import qualified Data.ByteString.Lazy as L


data LRedis = LRedis

instance Yesod LRedis where

mkYesod "LRedis" [parseRoutes|
    / HomeR GET
    /learnJson LearnJsonR GET
    /redisWorks RedisWorksR GET
    |]

getHomeR :: Handler RepHtml
getHomeR = do
    defaultLayout[whamlet|
    <p>Hi this is a headless API thing.
    |]

getLearnJsonR :: Handler RepJson
getLearnJsonR = do
    jsonToRepJson $ object [("json", ("ftw"::Text))]

getRedisWorksR :: Handler RepPlain
getRedisWorksR = do
    conn <- liftIO $ connect defaultConnectInfo
    liftIO $ runRedis conn $ do
        result <- Database.Redis.get (fromString "hello")
        case result of
            Left e -> return $ RepPlain "Error"
            Right mAnswer -> do
                case mAnswer of
                    Nothing -> return $ RepPlain "Not found."
                    Just x -> return $ RepPlain (toContent x)

main :: IO()
main = do
    warpDebug 3000 $ LRedis

再次,一切正常。如果您 curl /redisWorks,它将返回存储在 redis 中“hello”中的字符串,或者如果您 curl /learnJson,它将返回 JSON,但我想将 redis 答案作为 JSON 给出,而不是纯字符串。我以为我可以天真地将两者结合起来,例如:

getRedisJsonR :: Handler RepJson
getRedisJsonR = do
    conn <- liftIO $ connect defaultConnectInfo
    liftIO $ runRedis conn $ do
        result <- Database.Redis.get (fromString "hello")
        case result of
            Left e -> jsonToRepJson $ object [("response", ("error"::Text))]
            Right mAnswer -> do
                case mAnswer of
                    Nothing -> jsonToRepJson $ object [("response", ("Nothing"::Text))]
                    Just x -> jsonToRepJson $ object [("response", ((decodeUtf8 x)::Text))]

但是在添加路由 /redisJson RedisJsonR GET 之后,它会因为这个编译错误而失败:

Couldn't match expected type `Redis a0'
            with actual type `GHandler sub0 master0 RepJson'
In the expression:
  jsonToRepJson $ object [("response", ("error" :: Text))]
In a case alternative:
    Left e -> jsonToRepJson $ object [("response", ("error" :: Text))]
In a stmt of a 'do' block:
  case result of {
    Left e -> jsonToRepJson $ object [("response", ("error" :: Text))]
    Right mAnswer
      -> do { case mAnswer of {
                Nothing -> ...
                Just x -> ... } } }

它似乎在告诉我,如果出现错误,我需要对 result 做一些不同的事情,但我不知道那会是什么,或者鉴于 RepPlain 版本正在运行,为什么有必要这样做。

有没有在 Yesod 中将结果从 Redis 获取到 JSON 的示例?
是不是我在 IO 上做错了什么?

Hedis 文档的便捷链接:http://hackage.haskell.org/package/hedis 感谢您帮助我。如果它变得超级简单,再次抱歉。

【问题讨论】:

    标签: json haskell io redis yesod


    【解决方案1】:
    getRedisJsonR :: Handler RepJson
    getRedisJsonR = do
        conn <- liftIO $ connect defaultConnectInfo
        res <- liftIO $ runRedis conn $ do
            result <- Database.Redis.get (fromString "hello")
            case result of
                Left e -> return $ jsonToRepJson $ object [("response", ("error"::Text))]
                Right mAnswer -> do
                    case mAnswer of
                        Nothing -> return $ jsonToRepJson $ object [("response", ("Nothing"::Text))]
                        Just x -> return $ jsonToRepJson $ object [("response", ((decodeUtf8 x)::Text))]
        res
    

    实际上,我不相信自己能够解释为什么这行得通,而您的原始代码却行不通——我每天都在 Haskell 中编程不到三个月,所以我对什么有了发展的直觉会工作,但我真的还没有在理论方面,特别是当涉及到堆叠的单子时,我认为这是我们在这里处理的(Redis 在 Handler 之上,反之亦然,而 liftIO 正在促进堆叠)。

    希望其他人可以参与进来——这似乎是一个很好的具体例子来说明一些 monad 概念。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-24
      • 2012-04-02
      • 2019-09-27
      • 1970-01-01
      相关资源
      最近更新 更多