Каков наилучший способ преобразовать ByteString в Int? - PullRequest
9 голосов
/ 17 января 2012

Я всегда сталкиваюсь со следующей ошибкой при попытке прочитать 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 it.Для этого я использую следующую функцию, скопированную из Интернета:

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 работает как положено.

  1. Почему это так?
  2. Каков наилучший способ преобразования ByteString в Int?

Ответы [ 2 ]

10 голосов
/ 17 января 2012

Как лучше всего преобразовать ByteString в X, зависит от X.Если у вас есть хорошее преобразование из String, то через Data.BytString.Char8.unpack может быть хорошо, если это ASCII ByteString.Для кодированных в UTF-8 ByteString с пакет utf8-string содержит функцию преобразования toString.Для некоторых конкретных типов, таких как Int, как указано в заголовке, существуют специальные более быстрые преобразования.Например Data.ByteString.Char8.readInt и readInteger.

9 голосов
/ 17 января 2012

Show используется для создания String представления чего-либо, что полезно для отладки и простого текстового сериализации . Класс типов Show - это не просто причудливый способ преобразования чего-либо в String. Вот почему ByteString добавляет к строке кавычки: потому что, возможно, легче читать ее таким образом при отладке или десериализации потока данных.

Вы можете использовать функцию Data.ByteString.Char8.unpack для преобразования ByteString в String, но имейте в виду, что при этом распаковывается ByteString байт на байт, что портит высокое значение Символы Unicode или другие символы, которые хранятся как более одного байта; если вы хотите сделать что-то иное, чем использование read для результата, я бы рекомендовал вместо этого преобразовать ByteString в Text, что обеспечивает большую гибкость в этой ситуации. Предполагая, что в этом случае используется кодировка UTF8 (как должно быть по умолчанию в Snap), вы можете использовать для этого функцию Data.Text.Encoding.decodeUtf8. Чтобы затем преобразовать значение Text в String с правильными символами Юникода, используйте Data.Text.unpack.

Если у вас есть String, вы можете read его сколько захотите; в качестве альтернативы, вы можете выбрать считывание значения Text напрямую, используя функции модуля Data.Text.Read.

...