【问题标题】:Clumsy Looking Type Signature for ByteStrings in Haskell HTTP ResponseHaskell HTTP 响应中 ByteStrings 的笨拙的类型签名
【发布时间】:2016-12-12 01:29:07
【问题描述】:

我正在试验 http-conduit 库并有这个简单的例子:

#!/usr/bin/env stack
{- stack
    --resolver lts-7.12
    --install-ghc
    runghc
    --package http-conduit
-}
{-# LANGUAGE OverloadedStrings #-}

import Network.HTTP.Conduit
import Data.ByteString.Lazy.Internal

getUrl :: IO (Data.ByteString.Lazy.Internal.ByteString) ---eeew!
getUrl = do
  resp <- simpleHttp "http://www.stackoverflow.com"
  return resp

我从this post 了解到,与 [Char] 或字符串相比,我更喜欢将响应作为 ByteString。我认为 OverloadedStrings 杂注可能会减少这个问题,但相对于我的输出类型似乎没有改变。

该函数运行良好,并且尽职尽责地为 SO 的主页打印出一个简单的 http 响应,但是那个类型签名看起来真的很难看:

getUrl :: IO (Data.ByteString.Lazy.Internal.ByteString)

我不得不说,我从 Internet 示例中很少看到类似的东西(我们比椭圆形 Java 导入有更多的点,伙计)。是对的吗?如果我想返回一个响应然后开始解析它,比如使用 HXT 或 tagoup 或 attoparsec,这是正确的方法或类型签名吗?

我注意到,例如,当我开始添加接受参数的功能时,这变得更加丑陋,例如提供不同的 URL:

import Network.HTTP.Conduit
import Data.ByteString.Lazy.Internal

-- alright, first arg is now string for my url...
getUrl :: String -> IO (Data.ByteString.Lazy.Internal.ByteString)
getUrl url = do
  resp <- simpleHttp url
  return resp


main :: IO (ByteString)  -- what?!  inside the () ?
main = do
  getUrl "https://www.stackoverflow.com"

这似乎不健康。我应该如何理解如何正确构建它?

【问题讨论】:

    标签: haskell bytestring http-conduit


    【解决方案1】:

    您始终可以使用限定路径编写类型。但是,由于您已经导入了 Data.ByteString.Lazy.Internal 并且除非您在范围中有其他 ByteString 类型(如严格的类型),您可以简单地省略 Data.ByteString.Lazy.Internal

    getUrl :: IO ByteString
    

    另外,除非您有特殊需要导入Internal,否则我建议您只导入Data.ByteString.Lazy(它也会导出您正在使用的惰性ByteString 类型)。如果您在范围内同时拥有严格和懒惰的ByteString,我会将它们导入合格的:

     import qualified Data.ByteString as BS
     import qualified Data.ByteString.Lazy as BL
    

    那么BS.ByteString 是严格类型,BL.ByteString 是懒惰类型 - 无需写出完整的 Data.ByteString.ByteStringData.ByteString.Lazy.ByteString

    还值得一提(感谢@duplode)任何一个字节串模块通常都是最好的导入限定,因为它们定义了一大堆与前奏(以及彼此)冲突的函数。

    最后,请注意,类型周围的括号本身没有任何作用。 (ByteString)ByteString 是相同的。因此,我不会包括它们。


    与您的问题无关,但对您的一元代码有一些评论:

    • 每次你写类似的东西

      do x <- e
         return x
      

      它可以只替换为e

    • 每次你写类似的东西

      do e
      

      可以替换为e

    【讨论】:

    • 作为脚注,值得一提的是,导入合格的字节串模块也有助于避免与 Prelude 的名称冲突,例如 mapreadFile
    • 谢谢,@Alec。试图解决这个问题的一些事情。如果我只导入 Data.ByteString,它似乎不匹配:• Couldn't match type ‘Data.ByteString.Lazy.Internal.ByteString’ with ‘ByteString’
    • 而且 (2),我在试图让我的 monad 与你的 cmets 匹配时做错了什么?我正在尝试:getUrl :: String -&gt; ByteString getUrl = do simpleHttp url 我得到:Variable not in scope: url :: String
    • @Mittenchops 对于您的第一条评论 - 这是我的错(我已经确定了答案)。您需要导入 Data.ByteString.Lazy 而不仅仅是 Data.ByteString(您需要惰性版本,而不是严格版本)。至于第二个:getUrl url = simpleHttp url就够了,main = getUrl "https://www.stackoverflow.com"就够了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 2017-09-05
    相关资源
    最近更新 更多