Haskell函数extractValues类型匹配错误求助:Response String与[Char]不匹配
解决Haskell中Response String与[Char]类型不匹配问题
咱们先拆解一下你遇到的两个类型错误,然后一步步修复代码:
错误根源分析
- 第一个类型不匹配:错误提示
Couldn't match type ‘Response String’ with ‘[Char]’,是因为你直接把Response String类型的response变量当成了普通String来用。Response是HTTP客户端返回的完整响应对象,包含状态码、请求头和响应体等信息,你需要用responseBody函数提取其中的字符串内容。 - 第二个类型不匹配:你的
extractValues函数签名要求返回WeatherValues,但在case result of的Nothing分支里返回了字符串"Invalid JSON!",这和函数的返回类型完全不兼容,Haskell肯定会报错。 - 额外小问题:构造
WeatherValues时,你错误地写了WeatherValues temp_min (getTempMin info)——temp_min是记录的字段名,不是值,而且WeatherValues需要两个参数(最低温和最高温),你只传了一个。
修复后的完整代码
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} module PrepareAnswer where import Data.Text import Data.Aeson import Network.HTTP.Client (Response(..)) -- 明确导入responseBody所需的类型和函数 import GHC.Generics import Control.Monad import Data.Maybe import Data.Aeson.Encode.Pretty import Data.ByteString import AskWeather import Data.Aeson.Types import Data.ByteString.Char8 data TempUnits = Celsiuses | Farenheits deriving (Generic, Show) data WeatherValues = WeatherValues { temp_min :: Text , temp_max :: Text } deriving (Show) -- 修正后的extractValues函数 extractValues :: Response String -> WeatherValues extractValues response = let rawJSON = responseBody response -- 用responseBody提取响应体的字符串内容 jsonBytes = Data.ByteString.Char8.pack rawJSON -- 转成decodeStrict需要的ByteString result = decodeStrict jsonBytes :: Maybe Object in case result of -- 返回默认空值的WeatherValues,保证类型匹配 Nothing -> WeatherValues "" "" -- 正确传入最低温和最高温的字段值 Just info -> WeatherValues (getTempMin info) (getTempMax info) getTempMin :: Object -> Text -- 用fromMaybe简化空值处理 getTempMin info = fromMaybe "" (parseMaybe extractTempMin info) where extractTempMin = \info -> info .: "main" >>= \mainInfo -> mainInfo .: "temp_min" -- 补充获取最高温的函数 getTempMax :: Object -> Text getTempMax info = fromMaybe "" (parseMaybe extractTempMax info) where extractTempMax = \info -> info .: "main" >>= \mainInfo -> mainInfo .: "temp_max"
关键修改点说明
- 提取响应体:导入
Network.HTTP.Client (Response(..))后,用responseBody response获取真正的JSON字符串内容,解决了第一个类型不匹配问题。 - 统一返回类型:把
Nothing分支的返回值改成WeatherValues "" "",确保和函数签名的返回类型一致。 - 完善数据构造:补充
getTempMax函数,并在构造WeatherValues时正确传入两个字段的值。 - 简化空值处理:用
fromMaybe ""替代冗余的case表达式,让代码更简洁。
更严谨的错误处理方案(可选)
如果想让调用者明确知道JSON解析或字段提取是否失败,可以把extractValues的返回类型改成Maybe WeatherValues:
extractValues :: Response String -> Maybe WeatherValues extractValues response = let rawJSON = responseBody response jsonBytes = Data.ByteString.Char8.pack rawJSON result = decodeStrict jsonBytes :: Maybe Object in result >>= \info -> do minTemp <- parseMaybe extractTempMin info maxTemp <- parseMaybe extractTempMax info return $ WeatherValues minTemp maxTemp where extractTempMin = \info -> info .: "main" >>= \mainInfo -> mainInfo .: "temp_min" extractTempMax = \info -> info .: "main" >>= \mainInfo -> mainInfo .: "temp_max"
这种方式下,任何环节失败都会返回Nothing,调用者可以根据这个结果做针对性的错误处理。
内容的提问来源于stack exchange,提问作者MixFix Chanel
相关产品推荐
相关产品推荐

