我知道如何使用unpack将ByteString转换为String,但我正在努力弄清楚如何将IO ByteString(这是我从HaskellNet中的fetchHeader函数返回的内容)转换为IO String。我基本上试图做这样的事情
getAllHeadersForMessageUID :: IMapConnection -> UID -> IO String
getAllHeadersForMessageUID connection uid = do
headers <- fetchHeader connection uid
return (headers >>= BS.unpack)
错误消息对我没有意义
Couldn't match expected type ‘[BS.ByteString]’
with actual type ‘BS.ByteString’
In the first argument of ‘(>>=)’, namely ‘headers’
In the first argument of ‘return’, namely ‘(headers >>= BS.unpack)
我不知道为什么会出现ByteString列表。
答案 0 :(得分:8)
尝试使用return $ BS.unpack headers
代替return (headers >>= BS.unpack)
。
如果标题是ByteStrings列表,请尝试return $ map BS.unpack headers
。
除了碰巧输入类型检查(我假设BS.unpack headers
有效),这是一种思考问题的方法:
headers
是纯值BS.unpack
是纯函数headers >>= ...
没有意义,因为>>=
的LHS需要是monadic计算... >>= BS.unpack
没有意义,因为>>=
的RHS需要是一个产生monadic计算的函数BS.unpack headers
是我们想要返回的字符串,但它是一个纯值return
将纯值提升为monadic计算更新
以下代码显示,如果fetchHeader
的类型为IO [BS.ByteString]
,那么您的代码将输入check:
import Data.ByteString.Char8 as BS
fetchHeader :: IO [BS.ByteString] -- this works
-- fetchHeader :: IO BS.ByteString -- this doesn't
fetchHeader = undefined
foo :: IO String
foo = do
headers <- fetchHeader
return $ headers >>= BS.unpack
另一方面,如果您将其类型更改为IO BS.ByteString
,则会收到您遇到的错误。
更新2 :
有趣的是,当headers
是ByteStrings列表时,表达式headers >>= BS.unpack
确实有意义并且相当于:
concat $ map BS.unpack headers
答案 1 :(得分:0)
User5402的回答假设ByteString是纯ASCII(如果你是唯一一个使用你代码的人,那就没关系,但是如果你打算分享它,有几个原因可能是个坏主意) 如果ByteString使用UTF-8编码:您可以将其转换为String,如下所示:
import qualified Codec.Binary.UTF8.String as UTF8
foo b = do
bs <- b
return $ UTF8.decode $ unpack bs
我不确定如何处理其他编码,例如Windows代码页(除了设置句柄的编码,这不适用于此处)。