【问题标题】:Haskell: Understanding type conversion mechanics by `fromIntegral`Haskell:通过“fromIntegral”了解类型转换机制
【发布时间】:2019-04-04 21:47:35
【问题描述】:

通过fromIntegral理解类型转换

所以,我最近遇到了很多类型转换错误。这让我开始使用fromIntegral,尽管我对它的工作方式感到很困惑。

minimalExample :: Integer -> Integer
minimalExample a = truncate y
    where
        x = fromIntegral (a + 10)
        y = x - 12 * (x / 13)

注意我必须如何使用fromIntegral 来确保x(/) 运算符的正确类型。如果 x 是 Integral 类型,它就不会起作用。对 GHCI 中的函数的类型检查给了我这个信息:

Prelude> :t fromIntegral
fromIntegral :: (Integral a, Num b) => a -> b

Prelude> :t (/)
(/) :: Fractional a => a -> a -> a

显然fromIntegralInt/Integer 转换为一些Num 类类型(哪个?我不知道)。除法中缀运算符需要两个分数作为输入。现在看看this graphic,它总结了 Haskell 中的标准类型-类-关系。

Num 高于Fractional,这意味着不是每个Num-Type 都是Fractional。那么为什么(/) 接受一个通用的Num-type 作为参数呢?

我认为这是因为fromIntegral 并没有真正转换为Num(它们甚至都不能实例化,是吗?只能由具体类型继承),而是直接转换为DoubleFloat

如果是这样,它实际上转换为哪一个?为什么它实际上不在其定义中列出具体类型,而不是模糊和通用的Num 类类型?

【问题讨论】:

  • “那么为什么 (/) 接受一个通用的 Num 类型作为参数呢?”它没有。它只接受Fractional 的实例。但是由于FractionalNum 的子类,并且fromIntegral 可以生成任何NumfromIntegral 也可以生成Fractional - 因为它必须与(/) 一起使用。至于为什么这些函数没有在其定义中列出具体类型,那是因为这会不必要地限制它们的使用——但由于是多态的,它们可以在更多情况下使用。
  • PS 最近在this question 有很多类似的问题讨论
  • “显然 fromIntegral 将 Int/Integer 转换为某种 Num 类类型(哪个?我不知道)。”我喜欢将其视为一个非确定性函数,它将其参数转换为具有Num 实例的 all 类型的值。这些值以叠加的形式存在,直到您“观察”到所请求类型的值。

标签: haskell types


【解决方案1】:

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)

我当然做到了!但事实并非如此。可怕的单态限制开始生效,并迫使xy 在受约束类型n 中是单态的,因为它们不是(语法上的)函数。是的,单态限制很奇怪。

【讨论】:

    猜你喜欢
    • 2016-06-01
    • 2011-03-28
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    相关资源
    最近更新 更多