"appropriate value of type `Integer`" 是什么,我可以写一个吗?还有新类型

what is the "appropriate value of type `Integer`" and can I write one; also newtypes

Haskell 2010 年报告第 6.4.1 节说

An integer literal represents the application of the function fromInteger to the appropriate value of type Integer.

那 "appropriate value" 是什么样子的?我可以把它写在 source Haskell 中吗?我当然可以写

x :: Integer
x = 4

但是这个等式等价于

x = (fromInteger 4) :: Integer

编辑: 嗯,以避免无限倒退,可能应该是

x = (fromInteger 4?) :: Integer

其中 4? 是类型 Integer 的神秘值 4

所以它选择了 fromIntegerInteger 重载。文字的类型(在原来的 x = 4 中)仍然是 4 :: Num a => a,它不是类型 Integer.

我正在考虑这个 wrt newtypes:

{-# LANGUAGE  GeneralisedNewtypeDeriving  #-}

newtype Age = MkAge Int  deriving (Num, Eq, Ord, Show)
                        -- fromInteger is in Num
y :: Age
y = 4  
z = (4 + 5 :: Age)      -- no decl for z, inferred :: Age

如果我问 show y 我会看到 MkAge 4;如果我问 show x,我会看到普通的 4。那么 Integers 是否有一些不可见的构造函数?

newtypes的补充问题:既然我会写z = (4 + 5 :: Age),构造函数MkAge真的有必要吗?

mkAge2 :: Age -> Age
mkAge2 = id

w = mkAge2 4

mkAge3 :: Integer -> Age
mkAge3 = fromInteger

u = mkAge3 4

如果我想要一些前缀,似乎也能正常工作。

4 :: Integer就是这样一个值; 4 :: Int 不是。不要将文字 4 与它在源代码中表示的实际值系列混淆。

4 本身具有多态类型 Num a => a,这意味着在正确的上下文中,您可以 "extract" 从它获得类型 4 :: Integer 的值。这样的上下文是对 fromInteger 的调用,因为它需要一个 Integer 类型的值作为参数,而不是 Num a => a.

类型的值

当你在声明 x 确实是 Integer 类型的值后编写 x = 4 时,编译器会处理 "extracting" 值 4 :: Integer 从字面上看。


MkAge 是类型检查所必需的。 mkAge2 4 之所以有效,是因为您已经为 Age 定义(或至少派生)了 Num 的实例,这需要定义 fromInteger :: Integer -> AgemkAge2 隐式调用 4 上的 fromInteger 到 return MkAge 4,而 是传递给 [= 的值28=]。所以你仍然需要MkAge,你只是不必使用它明确。

Can I write it in source Haskell?

有点。

你可以写4 :: Integer但是4已经是fromInteger到"an appropriate value"的应用。 :: Integer 仅为 fromInteger 选择适当的重载。该应用程序的类型为 Integer,因此它可以像神奇的单态文字一样运行。

newtype Age = MkAge Int  deriving (Num, Eq, Ord, Show)

你现在可以写4 :: Age,这样就可以了。这与 Show 的作用无关。您可以编写自己的 Show 实例来打印普通的 4 而不是 MkAge 4。这就是所有内置类型的 Show 个实例的工作方式。以下是GHC特有的,其他实现可能有不同的细节,但大体原理很可能是一样的。

Prelude> :i Int
data Int = GHC.Types.I# Int#    -- Defined in ‘GHC.Types’
Prelude> :i Integer
data Integer
  = integer-gmp-1.0.2.0:GHC.Integer.Type.S# Int#
  | integer-gmp-1.0.2.0:GHC.Integer.Type.Jp# {-# UNPACK #-}integer-gmp-1.0.2.0:GHC.Integer.Type.BigNat
  | integer-gmp-1.0.2.0:GHC.Integer.Type.Jn# {-# UNPACK #-}integer-gmp-1.0.2.0:GHC.Integer.Type.BigNat
    -- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’

如您所见,IntInteger 有数据构造函数(它们不是 不可见的!)。我们可以使用 Int 没问题。

Prelude> :set -XMagicHash
Prelude> :t 3#
3# :: GHC.Prim.Int#
Prelude> :t GHC.Types.I# 3#
GHC.Types.I# 3# :: Int
Prelude> show 3
"3"
Prelude> show $ GHC.Types.I# 3#
"3"

好的,我们已经构建了一个带有构造函数的 Int,这不会干扰将其显示为普通的 3 一点点。它是将真正的构造函数应用于诚实的单态文字。 Integer 呢?

Prelude> GHC.Integer.Type.S# 3#

<interactive>:16:1: error:
    Not in scope: data constructor ‘GHC.Integer.Type.S#’
    No module named ‘GHC.Integer.Type’ is imported.
Prelude>

嗯。

Prelude> :m + GHC.Integer.Type

<no location info>: error:
    Could not load module ‘GHC.Integer.Type’
    it is a hidden module in the package ‘integer-gmp-1.0.2.0’

所以 Integer 构造函数对程序员是隐藏的(我想是故意的)。但是如果你自己写 GHC.Integer.Type,你就可以使用 GHC.Integer.Type.S# 3#。这具有类型 Integer 并且再次是真正的构造函数对诚实单态文字的应用。