Haskell 什么是「;“整数”类型的适当值;我能写一本吗;还有新类型
Haskell 2010报告第6.4.1节说 整数文本表示函数Haskell 什么是「;“整数”类型的适当值;我能写一本吗;还有新类型,haskell,typeclass,newtype,Haskell,Typeclass,Newtype,Haskell 2010报告第6.4.1节说 整数文本表示函数从整数到类型为整数的适当值的应用 “适当价值”是什么样的?我可以用Haskell的源代码写吗?我当然会写 x :: Integer x = 4 但这个等式相当于 x = (fromInteger 4) :: Integer 编辑:hmm以避免可能出现的无限回归 x = (fromInteger 4?) :: Integer 其中4?是类型Integer处的神秘值4 因此它选择了Integer重载fromInteger。文本的类型
从整数
到类型为整数
的适当值的应用
“适当价值”是什么样的?我可以用Haskell的源代码写吗?我当然会写
x :: Integer
x = 4
但这个等式相当于
x = (fromInteger 4) :: Integer
编辑:hmm以避免可能出现的无限回归
x = (fromInteger 4?) :: Integer
其中4?
是类型Integer
处的神秘值4
因此它选择了Integer
重载fromInteger
。文本的类型(在原始x=4
中)仍然是4::Num a=>a
,它不是类型整数
我在想这个wrtnewtype
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
如果我要求显示y
我会看到MkAge 4
;如果我要求显示x
我会看到普通的4
。那么,对于Integer
s,是否存在一些不可见的构造函数
对于newtype
s的补充q:既然我能写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
,这意味着在正确的上下文中,可以从中“提取”类型为4::Integer
的值。这样的上下文是对fromInteger
的调用,因为它需要一个Integer
类型的值作为参数,而不是Num a=>a
类型的值
当您在声明x
确实是Integer
类型的值之后编写x=4
时,编译器负责从文本中“提取”您的值4::Integer
MkAge
是进行类型检查所必需的mkAge2 4
的工作原理正是因为您为Age
定义了(或至少派生了)一个Num
实例,这需要定义fromInteger::Integer->Age
mkAge2
隐式调用4
上的fromInteger
返回mkage4
,这是传递给mkAge2
的值。因此,您仍然需要MkAge
,您不必显式地使用它。4::Integer
就是这样一个值<代码>4::Int不是。不要将文本4
与它在源代码中表示的实际值族混淆
4
本身具有多态类型Num a=>a
,这意味着在正确的上下文中,可以从中“提取”类型为4::Integer
的值。这样的上下文是对fromInteger
的调用,因为它需要一个Integer
类型的值作为参数,而不是Num a=>a
类型的值
当您在声明x
确实是Integer
类型的值之后编写x=4
时,编译器负责从文本中“提取”您的值4::Integer
MkAge
是进行类型检查所必需的mkAge2 4
的工作原理正是因为您为Age
定义了(或至少派生了)一个Num
实例,这需要定义fromInteger::Integer->Age
mkAge2
隐式调用4
上的fromInteger
返回mkage4
,这是传递给mkAge2
的值。所以您仍然需要MkAge
,您不必显式地使用它
我可以用Haskell的源代码写吗
有点
您可以将4::Integer
写入,但是4
已经是fromInteger
到“适当值”的应用程序<代码>::Integer仅为fromInteger
选择适当的重载。但是,应用程序的类型为Integer
,因此它可以像神奇的单态文字一样工作
您现在可以编写4::Age
,这样就可以了。这与Show
的功能无关。您可以编写自己的Show
实例来打印普通的4
,而不是MkAge 4
。这就是所有内置类型的显示
实例的工作方式。以下是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
一点点。它是真正的构造函数对诚实的单态文字的应用。那整数呢
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>GHC.Integer.Type.S#3#
:16:1:错误:
不在范围内:数据构造函数“GHC.Integer.Type.S#”
未导入名为“GHC.Integer.Type”的模块。
序曲>
嗯
Prelude>:m+GHC.Integer.Type
:错误:
无法加载模块“GHC.Integer.Type”
它是“integer-gmp-1.0.2.0”包中的隐藏模块
因此Integer
构造函数对程序员是隐藏的(我想是有意的)。但是如果您编写的是GHC.Integer.Type
本身,则可以使用GHC.Integer.Type.S#3
。它的类型为Integer
,也是真正的构造函数对诚实的单态文字的应用
我可以用Haskell的源代码写吗
有点
你可以写<
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’