You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell从URL读取CSV报错:ByteString版本冲突问题求助

Haskell读取URL中CSV数据遇ByteString版本冲突问题

我刚学Haskell24小时,已经初步理解语法,但觉得它比Python复杂不少。尝试多种方法并查阅文档后,还是没法从URL读取CSV数据,怀疑是ByteString库的问题,代码如下:

{-# LANGUAGE OverloadedStrings #-}

import Network.HTTP.Conduit (simpleHttp)
import Data.Csv
import qualified Data.ByteString.Lazy as BL
import qualified Data.Vector as V

readCSV :: String -> IO (Either String (V.Vector BL.ByteString))
readCSV url = do
    csvData <- simpleHttp url
    return $ decode HasHeader csvData

main :: IO ()
main = do
    let url = "https://earthquake.usgs.gov/fdsnws/event/1/query?format=csv&starttime=2023-12-30&endtime=2023-12-31&minlatitude=32&maxlatitude=42&minlongitude=-124&maxlongitude=-114&minmagnitude=3"
    result <- readCSV url
    case result of
        Left err -> print err
        Right csv -> print csv

运行后报错信息:

• Couldn't match expected type ‘BL.ByteString’
                  with actual type ‘bytestring-0.11.5.3:Data.ByteString.Lazy.Internal.ByteString’
      NB: ‘BL.ByteString’
            is defined in ‘Data.ByteString.Lazy.Internal’
                in package ‘bytestring-0.12.0.2’
          ‘bytestring-0.11.5.3:Data.ByteString.Lazy.Internal.ByteString’
            is defined in ‘Data.ByteString.Lazy.Internal’
                in package ‘bytestring-0.11.5.3’
    • In the second argument of ‘decode’, namely ‘csvData’
      In the second argument of ‘($)’, namely ‘decode HasHeader csvData’
      In a stmt of a 'do' block: return $ decode HasHeader csvData
   |
11 |     return $ decode HasHeader csvData

问题原因

这个错误是ByteString库版本冲突导致的:项目依赖的bytestring是0.12.0.2版本,但network-conduit(或其依赖)使用的是0.11.5.3版本,两个版本的ByteString类型属于不同的包实例,编译器无法匹配。

解决方法

  • 统一依赖版本:在项目的cabal.project或stack.yaml中强制指定bytestring版本,让所有依赖统一使用同一个版本。比如用Cabal的话,在cabal.project中添加:
    constraints: bytestring == 0.12.0.2
    
    若0.11.5.3版本兼容性更好,也可以指定该版本。
  • 清理并重构项目:执行cabal clean && cabal build(Cabal环境)或stack clean && stack build(Stack环境),清除旧构建缓存后重新编译。
  • 排查依赖树:用cabal list --installed bytestring或stack ls dependencies查看已安装的依赖版本,确认冲突的具体来源。

额外优化建议

当前代码返回的是原始CSV行的V.Vector BL.ByteString,如果想解析成具体的业务数据类型,可以定义数据类型并实现FromRecord实例,示例如下:

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

import Network.HTTP.Conduit (simpleHttp)
import Data.Csv
import qualified Data.ByteString.Lazy as BL
import qualified Data.Vector as V
import GHC.Generics

-- 定义地震数据类型,字段需和CSV表头对应
data Earthquake = Earthquake
    { time :: String
    , latitude :: Double
    , longitude :: Double
    , mag :: Double  -- 对应CSV中的"mag"字段
    } deriving (Show, Generic)

-- 自动生成FromRecord实例
instance FromRecord Earthquake

readCSV :: String -> IO (Either String (V.Vector Earthquake))
readCSV url = do
    csvData <- simpleHttp url
    return $ decode HasHeader csvData

main :: IO ()
main = do
    let url = "https://earthquake.usgs.gov/fdsnws/event/1/query?format=csv&starttime=2023-12-30&endtime=2023-12-31&minlatitude=32&maxlatitude=42&minlongitude=-124&maxlongitude=-114&minmagnitude=3"
    result <- readCSV url
    case result of
        Left err -> print err
        Right csv -> V.mapM_ print csv

这样就能直接解析出CSV中的具体字段,比原始ByteString更易处理。


内容的提问来源于stack exchange,提问作者Hafid Traikzi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 17:40:34