"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
。
所以它选择了 fromInteger
的 Integer
重载。文字的类型(在原来的 x = 4
中)仍然是 4 :: Num a => a
,它不是类型 Integer
.
我正在考虑这个 wrt newtype
s:
{-# 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
。那么 Integer
s 是否有一些不可见的构造函数?
newtype
s的补充问题:既然我会写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 -> Age
。 mkAge2
隐式调用 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’
如您所见,Int
和 Integer
有数据构造函数(它们不是 不可见的!)。我们可以使用 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
并且再次是真正的构造函数对诚实单态文字的应用。
Haskell 2010 年报告第 6.4.1 节说
An integer literal represents the application of the function
fromInteger
to the appropriate value of typeInteger
.
那 "appropriate value" 是什么样子的?我可以把它写在 source Haskell 中吗?我当然可以写
x :: Integer
x = 4
但是这个等式等价于
x = (fromInteger 4) :: Integer
编辑: 嗯,以避免无限倒退,可能应该是
x = (fromInteger 4?) :: Integer
其中 4?
是类型 Integer
的神秘值 4
。
所以它选择了 fromInteger
的 Integer
重载。文字的类型(在原来的 x = 4
中)仍然是 4 :: Num a => a
,它不是类型 Integer
.
我正在考虑这个 wrt newtype
s:
{-# 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
。那么 Integer
s 是否有一些不可见的构造函数?
newtype
s的补充问题:既然我会写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 -> Age
。 mkAge2
隐式调用 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’
如您所见,Int
和 Integer
有数据构造函数(它们不是 不可见的!)。我们可以使用 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
并且再次是真正的构造函数对诚实单态文字的应用。