尝试读取ByteString时,我总是遇到以下错误:
Prelude.read: no parse
以下是在浏览器中呈现时会导致此错误的代码示例:
factSplice :: SnapletSplice App App
factSplice = do
mbstr <- getParam "input" -- returns user input as bytestring
let str = maybe (error "splice") show mbstr
let n = read str :: Int
return [X.TextNode $ T.pack $ show $ product [1..n]]
或者更简单:
simple bs = read (show bs) :: Int
出于某种原因,在show bs
之后,结果字符串包含引号。
因此,为了解决错误,我必须删除引号然后read
它。
我使用从互联网复制的以下功能来执行此操作:
sq :: String -> String
sq s@[c] = s
sq ('"':s) | last s == '"' = init s
| otherwise = s
sq ('\'':s) | last s == '\'' = init s
| otherwise = s
sq s = s
然后simple bs = read (sq.show bs) :: Int
按预期工作。
答案 0 :(得分:10)
将ByteString
转换为X
的最佳方式取决于X
。如果您从String
转换得很好,那么通过Data.BytString.Char8.unpack
进行转换可能会很好,如果它是ASCII ByteString
。对于UTF-8编码的ByteString
,utf8-string包中包含转换函数toString
。对于某些特定类型,例如标题中提到的Int
,存在特殊的更快转换。例如Data.ByteString.Char8.readInt
和readInteger
。
答案 1 :(得分:9)
Show
用于创建某事物的String
表示,这对调试和纯文本序列化非常有用。 Show
类型类不仅仅是将任何东西转换为String
的奇特方式。这就是ByteString
为字符串添加引号的原因:因为在调试或反序列化数据流时,以这种方式读取它会更容易。
您可以使用Data.ByteString.Char8.unpack
函数将ByteString
转换为String
,但请注意,这会解压缩ByteString
每字节字节数,这会高度混乱-value Unicode字符或存储为多个字节的其他字符;如果您想对结果使用read
以外的其他操作,我建议您将ByteString
转换为Text
,这样可以在这种情况下提供更大的灵活性。假设在这种情况下你的编码是UTF8(因为它应该是Snap中的默认值),你可以使用Data.Text.Encoding.decodeUtf8
函数。要使用正确的Unicode符号将Text
值转换为String
,请使用Data.Text.unpack
。
获得String
后,您可以随心所欲read
获取;或者,您可以选择使用Data.Text.Read
模块中的函数直接读取Text
值。