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)
Оба base
и fromBeforeOp
дают одинаковый (правильный по отношению к определению Inverted
) ответ 57
, тогда как fromAfterOp
т 27
.