【发布时间】:2015-09-07 13:30:47
【问题描述】:
我正在阅读 Type 类,Chapter 2 of Learn You Haskell For Great Good。我的问题是为什么 4 + 3.2 有效,但长度 [1, 2, 3, 4] + 3.2 无效,为什么我们需要在第二种情况下使用 fromIntegral 函数。 Num 和 Integral 类型类之间是否没有关系。如何找到一个类型的实例是哪些类?
【问题讨论】:
我正在阅读 Type 类,Chapter 2 of Learn You Haskell For Great Good。我的问题是为什么 4 + 3.2 有效,但长度 [1, 2, 3, 4] + 3.2 无效,为什么我们需要在第二种情况下使用 fromIntegral 函数。 Num 和 Integral 类型类之间是否没有关系。如何找到一个类型的实例是哪些类?
【问题讨论】:
在这种情况下,使用 ghci 检查类型,例如它会告诉您第一次输入:
Prelude> :t 4 + 3.2
4 + 3.2 :: Fractional a => a
这里fromInteger 是隐式使用的(4)。
在第二种情况下,您会遇到问题,length 是 :: [a] -> Int(在较新的 GHC 中有点不同),3.2 仍然是 :: Fractional a => a 但 (+) 是 :: Num a => a -> a -> a(它需要相同参数类型a) - 现在Int 不是Fractional 的实例,您会收到错误消息。
PS(原来的答案已经消失)- 最简单的方法是使用 GHCi 使用 :i 本身:
Prelude> :i Int
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in ‘GHC.Types’
instance Bounded Int -- Defined in ‘GHC.Enum’
instance Enum Int -- Defined in ‘GHC.Enum’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Read Int -- Defined in ‘GHC.Read’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’
但请记住,这将取决于加载的模块 - 例如,当您 import Test.QuickCheck 时,您会看到 Int 现在也是 Arbitrary 的实例:
Prelude Test.QuickCheck> :i Int
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in ‘GHC.Types’
instance Bounded Int -- Defined in ‘GHC.Enum’
instance Enum Int -- Defined in ‘GHC.Enum’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Read Int -- Defined in ‘GHC.Read’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’
instance [overlap ok] [safe] CoArbitrary Int
-- Defined in ‘Test.QuickCheck.Arbitrary’
instance [overlap ok] [safe] Arbitrary Int
-- Defined in ‘Test.QuickCheck.Arbitrary’
【讨论】:
length 将其输出类型固定为Int(与3.2 不兼容)而不是任何Num。您正在寻找的功能是:
genericLength :: Num i => [b] -> i
【讨论】: