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

如何覆盖aeson包中ToJSON (Ratio Integer)的类型类实例?

解决Aeson中Ratio Integer的ToJSON实例重叠问题

优先推荐:用newtype包装类型

Haskell的类型类实例绑定到具体类型,直接覆盖已有实例会触发重叠错误,最稳妥的方式是用newtype给Ratio Integer套一层新类型,再为这个新类型定义你需要的ToJSON实例:

import Data.Aeson (ToJSON(..))
import Data.Ratio (Ratio, numerator, denominator)
import Data.Text (pack)

newtype FloatRatio = FloatRatio (Ratio Integer)

instance ToJSON FloatRatio where
  toJSON (FloatRatio r) = 
    let floatVal = (fromIntegral $ numerator r) / (fromIntegral $ denominator r) :: Double
    in String $ pack $ show floatVal

使用时把Ratio Integer值用FloatRatio包装即可,比如toJSON $ FloatRatio (3 % 4)会输出"0.75"。

不推荐:启用重叠实例编译选项

如果一定要直接覆盖原实例,可以通过GHC编译pragma强制开启重叠实例支持,但这种做法会破坏类型类一致性,可能导致依赖默认实例的其他代码行为异常,维护成本很高:

在自定义实例上方添加{-# OVERLAPPING #-}pragma:

{-# OVERLAPPING #-}
instance ToJSON (Ratio Integer) where
  toJSON r = 
    let floatVal = (fromIntegral $ numerator r) / (fromIntegral $ denominator r) :: Double
    in String $ pack $ show floatVal

注意:原代码里直接用numerator r / denominator r是整数除法,结果还是整数,必须用fromIntegral转成浮点数类型才能得到正确的小数格式。

内容的提问来源于stack exchange,提问作者Shawn Zhang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:12:33