function - Haskell 中函数类型的差异
问题描述
我一直在玩 Haskell 中的基本函数,并且对函数的以下类型声明之间的区别有点困惑f
f :: Integer -> Integer
相对
f :: Integral n => n -> n
到目前为止,我将这两者视为相同,但我确信这不是真的。有什么区别?
编辑:作为对第一个答案的回应,我想提出一个类似的例子,它更符合我持有的问题。
考虑以下声明
f :: Num n => n -> n
或者
f :: Num -> Num
每个提供什么功能?
解决方案
让我们重命名:
f :: Integer -> Integer
g :: (Integral n) => n -> n
我喜欢遵循一种相当普遍的做法,即在签名的约束部分添加括号。它有助于它脱颖而出。
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’
我们可以看到 3 个内置类型,它们是Integral
. 这意味着它g
同时具有三种不同的类型,具体取决于它的使用方式。
g :: Word -> Word
g :: Integer -> Integer
g :: Int -> Int
(如果您Integral
将来定义另一种类型,g
也会自动使用它)
变体就是一个很好的Word -> Word
例子,因为Word
s 不能是负数。 g
,当给定一个机器大小的正数时,返回另一个机器大小的正数,而f
可以返回任何整数,包括负数或大数。
Integral
是一个比较具体的类。使用 更容易看出Num
,它的方法更少,因此可以表示更多类型:
h :: (Num a) => a -> a
这也是 的概括f
,也就是说,您可以在预期具有 ' 类型的h
东西的地方使用。f
但h
也可以取一个复数,然后它会返回一个复数。
g
像's 和's 这样的签名的关键h
是它们适用于多种类型,只要返回类型与输入类型相同。
推荐阅读
- python - Python:评估我的函数的输出
- python - Python如何在对象内找到所有不可腌制的项目
- mysql - 从 MySQL 中的连接表中进行选择时,连接操作是否发生在选择之前?
- jssor - Jssor 可以支持百分比宽度吗?
- php - 在字符串中查找字符并将它们作为 php 中的链接
- pyspark - PySpark 毫秒的时间戳
- java - java.lang.IllegalArgumentException:参数值 [1604438222] 与预期类型不匹配 [java.lang.Integer (n/a)
- python - Pandas DataFrame to Reticulate 导致 IndexError
- angular - 使用 Angular CLI 预加载字体
- python - 具有定义轴限制的 Seaborn 联合图