Haskell a内值的算术运算,可能在记录内,或者如何为(Num(可能是a))编写实例
鉴于我有以下几点:Haskell a内值的算术运算,可能在记录内,或者如何为(Num(可能是a))编写实例,haskell,Haskell,鉴于我有以下几点: data Tick = Tick { _price :: Int } deriving (Eq, Ord) type High = Maybe Tick type Low = Maybe Tick data Candle = Candle { _open :: Open , _high :: High , _low :: Low , _close :: Close } deriving (Eq, Ord) makeLenses ''Candle 当
data Tick = Tick { _price :: Int } deriving (Eq, Ord)
type High = Maybe Tick
type Low = Maybe Tick
data Candle = Candle
{ _open :: Open
, _high :: High
, _low :: Low
, _close :: Close
} deriving (Eq, Ord)
makeLenses ''Candle
当我创建蜡烛时:
candle = ...
然后我希望使用计算高和低之间的差异:
axis = high - low
结果:
• No instance for (Num High) arising from a use of ‘-’
• In the expression: high - low
In an equation for ‘axis’: axis = high - low
我尝试过创建这样的实例:
instance Num High where
(-) (Just a) (Just b) = Just (a - b)
但这会导致错误:
• Illegal instance declaration for ‘Num High’
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use TypeSynonymInstances if you want to disable this.)
• In the instance declaration for ‘Num High’
所以我的问题是,
(Num High)
的实例应该是什么样的,才能允许我进行计算 arghhh。。。不不要那样做!你为什么认为这是个好主意
High
不是数字类型,因为它还包含非数字值Nothing
☆。(即使撇开任何这样的推理不谈,为既存在于已建立的标准库中的类型和类定义一个实例基本上也不是一个好主意,最肯定的不是base
。这样的实例会让所有了解这些库的人感到惊讶,并突然遇到意外的实例!而且,如果该实例确实有意义,那么GHC人员可能已经对其进行了定义。)
可能
的作用是,它迫使您考虑没有数字的情况,即没有给出上限或下限。我不知道你想在这种情况下采取什么样的行为,但可能的做法是立即将轴
-result也设为Nothing
。这可以通过使用Maybe
的应用程序实例轻松实现:
axis :: Maybe Int
axis = (-) <$> candle^.high <*> candle^.low
这就是说,如果您坚持定义该实例(您不应该这样做),那么它就很容易做到。首先,您可以分解类型同义词:
instance Num (Maybe Tick) where
Just (Tick a) - Just (Tick b) = Just . Tick $ a - b
_ - _ = Nothing
但这甚至没有必要;正如编译器已经暗示的那样,您可以通过类型同义词直接提供实例,但这并不简单。只需启用扩展
{-# LANGUAGE TypeSynonymInstances #-}
或
然后
instance Num High where
...
无论是好是坏,都被接受
&明星;
请注意,仅使用Applicative
定义Num
实例会带来麻烦:您希望-
和+
是可取消的,即(a-b)+b≡ a
。但是使用简单的a+b=(+)ab
(也可以编写(+)=liftA2(+)
)您将
(Just 1 - Nothing) + Nothing = Nothing
‡ Just 1
…请注意,浮点实例已经显示了大致相同的行为
Prelude> (1 - 1/0) + 1/0
NaN
但至少在那里,我们知道无穷大和NaN是一种极端情况,在这种情况下,一切都变得有点奇怪,而对于可能Int
来说,你会认为Nothing
是一个非常正常的值,“它只是不在这里”
†
一个更好的例子可能是
import Data.AdditiveGroup
instance AdditiveGroup Tick
…如果在数据定义中添加Generic
,则无需任何显式实现:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
data Tick = Tick { _price :: Int } deriving (Eq, Ord)
有了这个定义,你就可以
axis = (^-^) <$> candle^.high <*> candle^.low
轴=(^-^)烛光^.高烛光^.低烛光
arghhh。。。不不要那样做!你为什么认为这是个好主意
High
不是数字类型,因为它还包含非数字值Nothing
&star;。(即使撇开任何这样的推理不谈,为既存在于已建立的标准库中的类型和类定义一个实例基本上也不是一个好主意,最肯定的不是base
。这样的实例会让所有了解这些库的人感到惊讶,并突然遇到意外的实例!而且,如果该实例确实有意义,那么GHC人员可能已经对其进行了定义。)
可能
的作用是,它迫使您考虑没有数字的情况,即没有给出上限或下限。我不知道你想在这种情况下采取什么样的行为,但可能的做法是立即将轴
-result也设为Nothing
。这可以通过使用Maybe
的应用程序实例轻松实现:
axis :: Maybe Int
axis = (-) <$> candle^.high <*> candle^.low
这就是说,如果您坚持定义该实例(您不应该这样做),那么它就很容易做到。首先,您可以分解类型同义词:
instance Num (Maybe Tick) where
Just (Tick a) - Just (Tick b) = Just . Tick $ a - b
_ - _ = Nothing
但这甚至没有必要;正如编译器已经暗示的那样,您可以通过类型同义词直接提供实例,但这并不简单。只需启用扩展
{-# LANGUAGE TypeSynonymInstances #-}
或
然后
instance Num High where
...
无论是好是坏,都被接受
&明星;
请注意,仅使用Applicative
定义Num
实例会带来麻烦:您希望-
和+
是可取消的,即(a-b)+b≡ a
。但是使用简单的a+b=(+)ab
(也可以编写(+)=liftA2(+)
)您将
(Just 1 - Nothing) + Nothing = Nothing
‡ Just 1
…请注意,浮点实例已经显示了大致相同的行为
Prelude> (1 - 1/0) + 1/0
NaN
但至少在那里,我们知道无穷大和NaN是一种极端情况,在这种情况下,一切都变得有点奇怪,而对于可能Int
来说,你会认为Nothing
是一个非常正常的值,“它只是不在这里”
†
一个更好的例子可能是
import Data.AdditiveGroup
instance AdditiveGroup Tick
…如果在数据定义中添加Generic
,则无需任何显式实现:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
data Tick = Tick { _price :: Int } deriving (Eq, Ord)
有了这个定义,你就可以
axis = (^-^) <$> candle^.high <*> candle^.low
轴=(^-^)烛光^.高烛光^.低烛光
关键点在错误消息中:“其中T不是同义词”,解决方案也在那里“如果要禁用它,请使用TypeSynonymInstances”。当然,定义实例的方式,您还必须定义实例数勾号
谢谢@AdamSmith defining实例数勾号
,只要匹配的模式就足以让我通过此错误!关键点在错误消息中:“其中T不是同义词”,解决方案也是“如果要禁用它,请使用TypeSynonymInstances”。当然,定义实例的方式,您还必须定义实例数勾号
谢谢@AdamSmith defining实例数勾号
,只要匹配的模式就足以让我通过此错误!我想那太好了