将 Either Reply [Maybe ByteString] 处理成 [Maybe Text]
Process a Either Reply [Maybe ByteString] into a [Maybe Text]
以下代码使用 Hedis 运行 mget
命令,return 结果为 [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
到 return 一个 [Maybe Text]
,使用上面写的 bst
助手。我无法执行 pure $ bst <$> values
,因为这里有两个级别的解包:首先是 Maybe
,然后是 List
。有没有什么方法可以让这个函数 return 得到想要的类型,而不会淹没在嵌套的 case
语句的海洋中?
你问的本质上是如何 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
深度 fmap 三层。但在这一点上,将整个堆栈视为单个函子可能会更好,这可以通过 monad transformers.
来完成
以下代码使用 Hedis 运行 mget
命令,return 结果为 [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
到 return 一个 [Maybe Text]
,使用上面写的 bst
助手。我无法执行 pure $ bst <$> values
,因为这里有两个级别的解包:首先是 Maybe
,然后是 List
。有没有什么方法可以让这个函数 return 得到想要的类型,而不会淹没在嵌套的 case
语句的海洋中?
你问的本质上是如何 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
深度 fmap 三层。但在这一点上,将整个堆栈视为单个函子可能会更好,这可以通过 monad transformers.