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

如何编写(Num (Maybe a))实例?及Candle高低差计算的Num实例问题

Alright, let's break down your two Haskell Num instance questions with practical, working code and explanations—no jargon overload, promise!

1. Implementing Num (Maybe a) for arithmetic on wrapped values

To define a Num instance for Maybe a, we first need to ensure the inner type a is itself a Num (since we're doing arithmetic on its values). The core idea is to propagate Nothing through all operations (if any input is missing, the result is missing) and apply standard arithmetic to Just values.

Here's the complete instance:

instance Num a => Num (Maybe a) where
  -- Addition: Only compute if both values exist
  Just x + Just y = Just (x + y)
  _ + _ = Nothing

  -- Multiplication: Same logic as addition
  Just x * Just y = Just (x * y)
  _ * _ = Nothing

  -- Negation: Flip the sign of a wrapped value; leave Nothing as-is
  negate (Just x) = Just (negate x)
  negate Nothing = Nothing

  -- Absolute value: Apply to wrapped value
  abs (Just x) = Just (abs x)
  abs Nothing = Nothing

  -- Signum: Get the sign of the wrapped value
  signum (Just x) = Just (signum x)
  signum Nothing = Nothing

  -- Convert an integer to Maybe a: Wrap it in Just (since integers are always valid here)
  fromInteger n = Just (fromInteger n)

This instance behaves exactly as you'd expect:

  • Just 5 + Just 3 returns Just 8
  • Just 10 * Nothing returns Nothing
  • negate (Just (-4)) returns Just 4

2. Creating a Num High instance to calculate Candle high-low differences

First, let's assume your core types look like this (adjust if your actual definitions differ):

newtype High = High Double deriving (Show)
newtype Low = Low Double deriving (Show)
data Candle = Candle { high :: High, low :: Low } deriving (Show)

The error you're seeing happens because:

  1. High doesn't have a Num instance, so you can't use - on it
  2. High and Low are distinct types, so you can't directly subtract a Low from a High

Step 1: Define the Num High instance

We'll lift the Double Num behavior up to the High newtype—this lets us use arithmetic operators on High values:

instance Num High where
  High x + High y = High (x + y)
  High x * High y = High (x * y)
  negate (High x) = High (negate x)
  abs (High x) = High (abs x)
  signum (High x) = High (signum x)
  fromInteger n = High (fromInteger n)

Step 2: Convert Low to High for subtraction

Since Low and High both wrap numeric values, we can write a simple conversion function to make the types match:

lowToHigh :: Low -> High
lowToHigh (Low d) = High d

Step 3: Calculate the high-low difference

Now you can safely compute the difference with type-matched values:

highLowDiff :: Candle -> High
highLowDiff candle = high candle - lowToHigh (low candle)

Optional: Add a Num instance for Low (if needed)

If you want to do other arithmetic with Low values, you can mirror the High instance:

instance Num Low where
  Low x + Low y = Low (x + y)
  Low x * Low y = Low (x * y)
  negate (Low x) = Low (negate x)
  abs (Low x) = Low (abs x)
  signum (Low x) = Low (signum x)
  fromInteger n = Low (fromInteger n)

Common pitfalls to avoid

  • Forgetting to implement all Num methods: Haskell requires every method in the typeclass to be defined (you can't skip (+) just because you only need (-)).
  • Missing type constraints: Make sure any inner types (like a in Maybe a) have the necessary constraints (e.g., Num a).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:02:12