fromIntegral
的类型转换因此,最近我遇到了很多类型转换错误。这使我开始使用fromIntegral
,尽管我对它的工作方式感到困惑。
minimalExample :: Integer -> Integer
minimalExample a = truncate y
where
x = fromIntegral (a + 10)
y = x - 12 * (x / 13)
请注意,我必须如何使用fromIntegral
来确保x
的类型适合(/)
运算符。如果x
是整数类型,那将行不通。对GHCI中的函数进行类型检查会得到以下信息:
Prelude> :t fromIntegral
fromIntegral :: (Integral a, Num b) => a -> b
Prelude> :t (/)
(/) :: Fractional a => a -> a -> a
很显然,fromIntegral
将Int
/ Integer
转换为某种Num
类类型(哪个?我不知道)。除法中缀运算符期望两个小数作为输入。现在来看一下this graphic,它总结了Haskell中的标准type-class-relations。
Num
在Fractional
上方,这意味着并非每个Num
-Type都是Fractional
。那么,为什么(/)
接受通用的Num
类型作为参数呢?
我认为是因为fromIntegral
并没有真正转换为Num
(那些甚至不能实例化,它们吗?只能由具体类型继承),而是直接转换为Double
或Float
。
如果是,它将实际转换为哪一个?为什么它实际上没有在定义中列出该具体类型,而不是模糊且通用的Num
类类型?
答案 0 :(得分:5)
fromIntegral
不会转换为一些模糊的,不可知的Num
类型。它将转换为所需的内容。也就是说,fromIntegral
不会选择自己的结果类型。呼叫者可以。所以
fromIntegral :: Int -> Integer
fromIntegral :: Int -> Word
fromIntegral :: Integer -> Double
等等在这种情况下,类型检查器会推断出
minimalExample :: Integer -> Integer
minimalExample a = truncate y
where
x, y :: Fractional n => n
x = fromIntegral (a + 10)
y = x - 12 * (x / 13)
因为(/)
要求使用Fractional
类型。
然后使用默认机制来修复n
:
minimalExample :: Integer -> Integer
minimalExample a = truncate y
where
x, y :: Double
x = fromIntegral (a + 10)
y = x - 12 * (x / 13)
相反,您可能希望得到结果
minimalExample :: Integer -> Integer
minimalExample a = truncate (y :: Double)
where
x, y :: Fractional n => n
x = fromIntegral (a + 10)
y = x - 12 * (x / 13)
我当然做到了!但事实并非如此。可怕的单态性约束开始起作用,并迫使x
和y
在约束类型n
中是单态的,因为它们不是(从语法上)函数。是的,单态性限制很奇怪。