关于“Num'”的算术运算规则

时间:2018-06-03 08:53:13

标签: haskell polymorphism constants

常量在Haskell中是多态的。所以当我写:

foo = 5

这令人厌恶:

foo = fromInteger 5

但是如果添加算术表达式呢?

foo = 42 - 15

究竟是什么会被贬低?

foo = fromInteger (42 - 15)

for = fromInteger 42 - fromInteger 15

此外,观察此事的最简单可靠的方法是什么?

2 个答案:

答案 0 :(得分:5)

Haskell具有多态文字。 (默认只是数字,但GHC具有多态字符串文字和多态列表文字的语言扩展)

强制表达式(如fromInteger)仅对文字本身起作用,而不是表达式,所以

foo = 42 - 15

foo = fromInteger 42 - fromInteger 15

是等价的。

我们可以通过定义行为不同的Num实例来展示这种情况(例如,交换+-的地方)

newtype Inverted a = Inverted {unInvert :: a}
  deriving (Eq, Ord, Show)

instance (Num a) => Num (Inverted a) where
  (Inverted x) + (Inverted y) = Inverted (x-y)
  (Inverted x) - (Inverted y) = Inverted (x+y)
  signum = Inverted . signum . unInvert
  (Inverted x) * (Inverted y) = Inverted (x*y)
  abs = Inverted . abs . unInvert
  fromInteger = Inverted . fromInteger

base :: Inverted Double
base = 42 - 15

fromBeforeOp :: Inverted Double
fromBeforeOp = fromInteger 42 - fromInteger 15

fromAfterOp :: Inverted Double
fromAfterOp = fromInteger (42 - 15)

basefromBeforeOp都给Inverted的{​​{1}}答案提供了相同的内容(57的定义是正确的),fromAfterOp给出了27 templacte <T, Base> class ThrowIfNotBaseOf { void checkIt() { if(!std::is_base_of<Base, T>::value) { throw std::invalid_argument( "T must inherit from Time Class" ); } } public: TypeCheckThrow() { // default constructor checkIt(); } TypeCheckThrow(const TypeCheckThrow<T, Base> &) { // copy constructor checkIt(); } TypeCheckThrow(TypeCheckThrow<T, Base> &&) { // move constructor checkIt(); } }; template<class T> class B { ThrowIfNotBaseOf<T, Time> typeCheckThrow; T data; void do_someting() { data.t = 12.34; } }; }}

答案 1 :(得分:3)

很沮丧

foo = fromInteger 42 - fromInteger 15

您可以通过尝试

来观察
f :: Double -> Int -> String
f _ _ = "hello"

foo = 42 `f` 15

我们使用自定义f代替-。在调用f之前,必须将这两个文字转换为数字类型。转换f的结果将毫无意义,因为它不是数字类型。

使用-不会改变一般规则。