Haskell中函数类型的区别

Don*_*and 6 haskell function

我一直在玩Haskell中的基本函数,并且对于函数的以下类型声明之间的区别有点困惑 f

f :: Integer -> Integer
Run Code Online (Sandbox Code Playgroud)

f :: Integral n => n -> n
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已将这两者视为相同,但我确信这不是真的.有什么不同?

编辑:作为对第一个答案的回答,我想提出一个类似的例子,更多的是我所持的问题.

请考虑以下声明

f :: Num n => n -> n
Run Code Online (Sandbox Code Playgroud)

要么

f :: Num -> Num
Run Code Online (Sandbox Code Playgroud)

每个提供什么功能?

luq*_*qui 7

我们重命名:

f :: Integer -> Integer
g :: (Integral n) => n -> n
Run Code Online (Sandbox Code Playgroud)

我喜欢遵循一种相当常见的做法,即在签名的约束部分添加括号.它有助于它脱颖而出.

f :: Integer -> Integer 很简单,它需要一个整数并返回另一个整数.

至于g :: (Integral n) => n -> n:Integral不是一个类型本身,而是更像是一个谓词.有些类型Integral,有些类型不是.例如,Int是一种Integral类型,Double不是.

n是一个类型变量,它可以引用任何类型. (Integral n)是对类型变量的约束,它限制了它可以引用的类型.所以你可以这样读:

g获取任何类型 n的值并返回相同类型的值,前提是它是一个Integral类型.

如果我们检查Integral类型类:

ghci> :info Integral
class (Real a, Enum a) => Integral a where
  quot :: a -> a -> a
  rem :: a -> a -> a
  div :: a -> a -> a
  mod :: a -> a -> a
  quotRem :: a -> a -> (a, a)
  divMod :: a -> a -> (a, a)
  toInteger :: a -> Integer
 {-# MINIMAL quotRem, toInteger #-}
    -- Defined in ‘GHC.Real’
instance Integral Word -- Defined in ‘GHC.Real’
instance Integral Integer -- Defined in ‘GHC.Real’
instance Integral Int -- Defined in ‘GHC.Real’
Run Code Online (Sandbox Code Playgroud)

我们可以看到3种内置类型Integral.这意味着g 同时有三种不同的类型,具体取决于它的使用方式.

g :: Word -> Word
g :: Integer -> Integer
g :: Int -> Int
Run Code Online (Sandbox Code Playgroud)

(如果你Integral将来定义另一种类型,g也会自动使用它)

Word -> Word变种是一个很好的例子,由于Words不能是负数. g当给出一个正的机器大小的数字时,返回另一个正的机器大小的数字,而f可以返回任何整数,包括负数或巨大数.

Integral是一个相当具体的课程.它更容易看到Num,它有更少的方法,因此可以代表更多类型:

h :: (Num a) => a -> a
Run Code Online (Sandbox Code Playgroud)

这也是一个概括f,也就是说,你可以使用h具有f类型的东西的东西.但h也可以采用复数,然后返回一个复数.

g's和h's 这样的签名的关键是它们可以处理多种类型,只要返回类型与输入类型相同.