我可以在Haskell源代码中写它吗?
排序。
您可以编写4 :: Integer
,但是4
已经是fromInteger
的“适当值”的应用程序。 :: 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
,并且还是诚实的单态文字的真实构造函数的应用。
,
4 :: Integer
是这样的值; 4 :: Int
不是。不要将文字4
与它在源代码中表示的实际值系列混淆。
4
本身具有多态类型Num a => a
,这意味着在正确的上下文中,您可以从中“提取”类型4 :: Integer
的值。这样的上下文是对fromInteger
的调用,因为它期望将Integer
类型的值作为参数,而不是Num a => a
类型的值。
当您在声明x = 4
确实是类型x
的值后写Integer
时,编译器会为您的代码“提取”值4 :: Integer
从文字上看。
MkAge
是类型检查所必需的。 mkAge2 4
的工作正是因为您已经为Num
定义(或至少派生了)Age
的实例,这需要定义fromInteger :: Integer -> Age
。 mkAge2
隐式调用fromInteger
上的4
以返回MkAge 4
,并且那个是传递给mkAge2
的值。因此,您仍然需要MkAge
,而不必显式使用使用。
本文链接:https://www.f2er.com/3145295.html