代码之家  ›  专栏  ›  技术社区  ›  Jivan

将Any Reply〔Maybe ByteString〕处理为〔Maybe Text〕

  •  0
  • Jivan  · 技术社区  · 3 年前

    以下代码运行 mget 使用Hedis命令,并将结果作为 [Maybe BS.ByteString] :

    -- | Text to ByteString
    tbs :: Text -> BS.ByteString
    tbs = BS.pack . T.unpack
    
    
    -- | ByteString to Text
    bst :: BS.ByteString -> Text
    bst = T.pack . BS.unpack
    
    
    mgetRedis :: Redis.Connection -> [Text] -> IO [Maybe BS.ByteString]
    mgetRedis connection keys =
        runRedis connection action
        where
            action = do
    
                result <- Redis.mget $ tbs <$> keys
                -- `result` is of type `Either Reply [Maybe BS.ByteString]`
    
                case result of
                    Right values -> pure values
                    _            -> pure []
    

    首先,我发现这段代码相当混乱,想知道是否有办法让它更清晰。

    第二,我想 mgetRedis 返回a [Maybe Text] 相反,使用 bst 上面写的助手。我做不到 pure $ bst <$> values 因为这里有两个级别的解包:第一 Maybe 然后 List .这个函数有没有办法返回所需的类型,而不会淹没在嵌套的海洋中 case 声明?

    1 回复  |  直到 3 年前
        1
  •  1
  •   leftaroundabout    3 年前

    你问的基本上是如何 fmap 任意深入到一堆函数子中。这很容易通过作曲来完成 fmap s

    mgetRedis :: Redis.Connection -> [Text] -> IO [Maybe Text]
    mgetRedis connection keys =
        runRedis connection action
        where
            action = do
    
                result <- Redis.mget $ tbs <$> keys
                -- `result` is of type `Either Reply [Maybe BS.ByteString]`
    
                case result of
                    Right values -> pure $ fmap T.decodeUtf8 <$> values
                          -- equivalent to (fmap . fmap) T.decodeUtf8 $ values
                    _            -> pure []
    

    这个 fmap . fmap 模式重复,即你可以用 fmap . fmap . fmap 。但在这一点上,最好将整个堆栈视为一个函数子,这可以通过以下方式实现 莫纳德变压器 .

    推荐文章