0

我正在试验 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

我从这篇文章中了解到,我应该更喜欢作为 ByteString 的响应而不是 [Char] 或 String。我认为 OverloadedStrings 杂注可能会减少这个问题,但相对于我的输出类型似乎没有改变。

该函数工作正常,并且尽职尽责地为 SO 的主页打印出一个简单的 http 响应,但该类型签名看起来真的很难看:

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

而且我不得不说,我从互联网示例中很少看到类似的东西(我们有比椭圆 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"

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

4

1 回答 1

2

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

getUrl :: IO ByteString

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

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

然后BS.ByteString是严格类型和BL.ByteString惰性类型 - 无需写出完整的Data.ByteString.ByteStringor Data.ByteString.Lazy.ByteString

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

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


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

  • 每次你写类似的东西

    do x <- e
       return x
    

    它可以替换为 just e

  • 每次你写类似的东西

    do e
    

    它可以替换为e.

于 2016-12-12T01:48:02.013 回答