Data.ByteString.Lazy.Internal.ByteString to string?

Bit*_*ler 9 haskell

尝试编写一个返回计算机外部IP地址的模块.使用Network.Wreq get函数,然后应用镜头获取responseBody,我最终得到的类型是Data.ByteString.Lazy.Internal.ByteString.因为我想过滤掉结果体的尾随"\n",我想随后将它用于正则表达式.问题:regex库不接受看似非常具体的ByteString类型,我发现无法将其转换为String.

这是我到目前为止的微弱尝试(不编译).

{-# LANGUAGE OverloadedStrings #-}

module ExtIp (getExtIp) where
import Network.Wreq
import Control.Lens
import Data.BytesString.Lazy
import Text.Regex.Posix

getExtIp :: IO String
getExtIp = do
    r <- get "http://myexternalip.com/raw"
    let body = r ^. responseBody
    let addr = body =~ "[^\n]*\n"
    return (addr)
Run Code Online (Sandbox Code Playgroud)

所以我的问题很明显:如何将有趣的特殊ByteString转换为String?解释我如何自己处理这样的问题也是值得赞赏的.我试图用unpacktoString,但不知道该怎么导入如果它们存在让这些功能.

作为一个非常零星的haskell用户,我也想知道是否有人可以向我展示定义这样一个函数的惯用的haskell方式.毕竟,我在这里展示的版本没有考虑可能的运行时错误/异常.

Eri*_*ikR 11

简短回答:使用unpackData.ByteString.Lazy.Char8

更长的回答:

通常,当您想要将ByteString(任何种类)转换为String或Text时,您必须指定编码 - 例如UTF-8或Latin1等.

检索HTML页面时,您要使用的编码可能会作为<meta ...>标记显示在Content-type标头中或响应正文中.

或者你可以猜测身体的编码是什么.

在你的情况下,我认为你正在访问像http://whatsmyip.org这样的网站,你只需要解析你的IP地址.因此,如果不检查标题或浏览HTML,使用的安全编码将是Latin1.

要通过编码将ByteStrings转换为Text,请查看Data.Text.Encoding中的函数

例如,decodeLatin1功能.


eps*_*lbe 5

我根本不明白为什么你坚持使用Strings,当你ByteString手头已经有了更快/更有效的实现。导入regex几乎没有给你带来任何好处——为了解析 ip 地址,我会使用attoparsec它,它与ByteStrings 配合得很好。

这是一个不使用正则表达式但返回字符串的版本 - 注意我没有编译它,因为我现在没有 haskell 设置。

{-# LANGUAGE OverloadedStrings #-}

module ExtIp (getExtIp) where
import Network.Wreq
import Control.Lens
import Data.ByteString.Lazy.Char8 as Char8
import Data.Char (isSpace)

getExtIp :: IO String
getExtIp = do
    r <- get "http://myexternalip.com/raw"
    return $ Char8.unpack $ trim (r ^. responseBody)
  where trim = Char8.reverse . (Char8.dropWhile isSpace) . Char8.reverse . (Char8.dropWhile isSpace)
Run Code Online (Sandbox Code Playgroud)

  • 我想要的是返回一个不会产生额外工作的规范类型(例如这里的这个SO问题)。如果 Wreq 返回 String,我就不会遇到我所面临的麻烦。如果该语言没有规范的字符串类型,则每当使用库时,都会出现此类转换问题。你可以说我很守旧……但我更喜欢在界面边界上坚持一种规范类型。 (3认同)