繁体   English   中英

为什么这个Haskell表达式编译?

[英]Why does this Haskell expression compile?

以下是我写的一些定义,以避免混合货币

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

data EUR
data USD 

newtype Amount a = Amount Double deriving (Fractional, Num, Show)

eur :: Double -> Amount EUR
eur = Amount

usd :: Double -> Amount USD
usd = Amount
  • usd 34 + usd 3类型检查按预期
  • usd 33 + eur 33是预期的编译错误
  • 我很惊讶,但根据编译器我们usd 33 + 3是可以的。 我想避免的东西,并且不明白。 我怀疑这是因为Num实例,但那么第二种情况有什么不同?

你能解释一下为什么我们usd 33 + 3编译,如果有可能使类型检查器拒绝这个表达式。

Haskell中的数字有很多隐含性。 在心理上,你应该用fromInteger 3替换像3这样的每个数字。 由于Amount使用GeneralizedNewtypeDeriving作为Num类型类的一部分,因此它继承了一个fromInteger实例。 所以编译器正在这样做

usd 33 + 3
===                                      [implicit fromInteger & expand usd]
(Amount 33 :: Amount USD) + 
  fromInteger 3
===                                      [fromInteger :: Num a => a -> Amount a]
(Amount 33 :: Amount USD) + 
  (Amount 3 :: Amount a)
===                                      [unify a]
(Amount 33 :: Amount USD) + 
  (Amount 3 :: Amount USD)

当GHC派生Num类时,它为fromInteger函数提供了一个实现。 3这样的整数文字实际上具有类型Num a => a

ghci> :t (34)
(34) :: Num a => a

当类型检查器发现您尝试将Amount USD类型的值添加到3 ,它确定3 :: Amount USD ,这是有效的,因为它是Num类型类的成员。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM