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

如何让read函数无需类型注解自动识别Int与Double类型?

实现自动识别Int/Double的read函数

可以实现,但因为Haskell是静态类型语言,无法让函数直接返回不确定的Int或Double类型,需要用**求和类型(Sum Type)**来包裹两种可能的结果,下面提供两种可行方案:

方案一:自定义数据类型并实现Read实例

定义一个包含Int和Double的代数数据类型,为它实现Read实例,让解析逻辑优先尝试Double,失败再尝试Int:

data Number = IntNum Int | DoubleNum Double deriving (Show, Eq)

instance Read Number where
  readsPrec _ input =
    -- 先尝试解析为Double
    case reads input :: [(Double, String)] of
      [(d, "")] -> [(DoubleNum d, "")]
      -- 解析Double失败,尝试解析为Int
      _ -> case reads input :: [(Int, String)] of
             [(n, "")] -> [(IntNum n, "")]
             -- 都失败则返回空列表表示解析失败
             _ -> []

使用示例:

read "123" :: Number       -- 得到 IntNum 123
read "123.45" :: Number    -- 得到 DoubleNum 123.45

方案二:用Either实现辅助解析函数

如果不想自定义新类型,可以用Either嵌套来区分结果,写一个辅助函数先尝试解析Int,失败再解析Double:

readNumber :: String -> Either String (Either Int Double)
readNumber input =
  case reads input :: [(Int, String)] of
    [(n, "")] -> Right (Left n)
    _ -> case reads input :: [(Double, String)] of
           [(d, "")] -> Right (Right d)
           _ -> Left "输入不是有效的Int或Double格式"

使用示例:

readNumber "456"       -- Right (Left 456)
readNumber "456.78"    -- Right (Right 456.78)
readNumber "abc"       -- Left "输入不是有效的Int或Double格式"

说明

原生read函数需要明确的类型注解,因为它的类型Read a => String -> a要求编译时确定a的具体类型。通过上述方式,我们把两种可能的类型封装到一个求和类型中,让解析逻辑在运行时判断输入格式并返回对应的包裹值,从而实现自动识别的效果。

内容的提问来源于stack exchange,提问作者Guldam Kwak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:23:19