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

如何借助GHC扩展减少自定义Number类型的样板代码?

减少Haskell样板代码的方案(基于GHC扩展)

可以通过提取通用的类型提升函数,结合GHC的基础扩展(如LambdaCase)消除重复的模式匹配样板,以下是具体实现:

1. 定义通用提升函数

先封装针对Integer和Double的操作到Number类型的逻辑,避免重复编写模式匹配:

{-# LANGUAGE LambdaCase #-}

data Operation = Add | Sub | Mult | Div

data Number
    = IntVal Integer
    | FloatVal Double

-- 提升二元操作至Number类型
liftBinOp :: (Integer -> Integer -> Integer) -> (Double -> Double -> Double) -> Number -> Number -> Number
liftBinOp intOp floatOp lhs rhs = case (lhs, rhs) of
  (IntVal i, IntVal j) -> IntVal $ intOp i j
  (FloatVal x, FloatVal y) -> FloatVal $ floatOp x y
  _ -> undefined

-- 提升一元操作至Number类型(用于Num实例)
liftUnOp :: (Integer -> Integer) -> (Double -> Double) -> Number -> Number
liftUnOp intOp floatOp = \case
  IntVal i -> IntVal $ intOp i
  FloatVal x -> FloatVal $ floatOp x

2. 简化evaluate函数

每个Operation只需绑定对应的运算符,无需重复编写case逻辑:

evaluate :: Operation -> Number -> Number -> Number
evaluate Add = liftBinOp (+) (+)
evaluate Sub = liftBinOp (-) (-)
evaluate Mult = liftBinOp (*) (*)
evaluate Div = liftBinOp div (/)  -- 整数用div做除法,浮点数用/

3. 简化Num Number实例实现

复用提升函数实现Num的所有方法,避免重复样板:

instance Num Number where
  (+) = liftBinOp (+) (+)
  (-) = liftBinOp (-) (-)
  (*) = liftBinOp (*) (*)
  negate = liftUnOp negate negate
  abs = liftUnOp abs abs
  signum = liftUnOp signum signum
  fromInteger = IntVal

这种方案把重复的模式匹配逻辑抽离到通用函数中,后续新增操作或扩展类型时,只需补充对应的基础类型操作即可,大幅减少冗余代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:45:33