如果你在 GHCi 中输入
:i (->)
并点击 Enter 它返回以下内容:
data (->) t1 t2 -- Defined in ‘GHC.Prim’
infixr 0 `(->)`
instance Monad ((->) r) – Defined in ‘GHC.Base’
instance Functor ((->) r) – Defined in ‘GHC.Base’
instance Applicative ((->) a) – Defined in ‘GHC.Base’
instance Monoid b => Monoid (a -> b) – Defined in ‘GHC.Base’
从
data
关键字判断,它是某种类型构造函数,但它究竟构造了什么?这种类型的值构造函数是什么,如果它们存在的话?
当我了解到函数是
Functor
类型类的一部分并且在((->) r)
命令返回的类型类描述中被列为:i Functor
时,问题就出现了。我试图获取有关((->) r)
的信息,但无济于事。然后,在 Functor
类型类的描述中,我发现了 (Either a)
(其描述可以通过 :i Either
获得,即没有参数)并意识到我应该尝试 :i (->)
而不是,我做了并得到了上面显示的信息。
就是简单的函数类型构造器
类型
(->) a b
,更常写成中缀形式a -> b
,是函数的类型,它以类型a
为参数并返回类型b
。您会在任何函数的类型签名中看到这一点。
像
GHC.Prim
中的大多数其他东西一样,它是内置的并且有点“神奇”,因为它没有值构造函数 - 但你可以定义一个a -> b
类型的值,这是一个函数,我希望你已经知道的所有方式。
我要指出那种
(->)
。如果你问 ghci 它会告诉你它的参数是(提升)Type
s
ghci> :k (->)
(->) :: Type -> Type -> Type
TYPE
ghci> :set -fprint-explicit-runtime-reps
ghci> import GHC.Exts
ghci> :k (->)
(->) :: forall {rep1 :: RuntimeRep} {rep2 :: RuntimeRep}.
TYPE rep1 -> TYPE rep2 -> Type
RuntimeRep
参数化
type RuntimeRep :: Type
data RuntimeRep
= BoxedRep Levity -- ^ boxed; represented by a pointer
| IntRep -- ^ signed, word-sized value
| Int8Rep -- ^ signed, 8-bit value
| ..
| FloatRep -- ^ a 32-bit floating point number
| DoubleRep -- ^ a 64-bit floating point number
-- | Whether a boxed type is lifted or unlifted.
type Levity :: Type
data Levity = Lifted | Unlifted
Type
实际上是的同义词
type Type :: Type
type Type = TYPE LiftedRep
LiftedRep
是被装箱和提升的运行时表示的同义词(这是 Haskell 中的大多数类型,如 Int
或 Bool
)。
type LiftedRep :: RuntimeRep
type LiftedRep = BoxedRep Lifted
通过在运行时表示上的多态性,
(->)
可以接受未装箱的参数,如 Int# :: TYPE IntRep
和 Double# :: TYPE DoubleRep
,以及其他具有不寻常表示的奇怪类型:
ghci> :set -XMagicHash
ghci> :k Int# -> Double#
Int# -> Double# :: Type
此外,由于线性类型扩展,
(->)
实际上是FUN
的类型同义词,
FUN :: Multiplicity -> TYPE rep1 -> TYPE rep2 -> Type
Many :: Multiplicity
”
type (->) :: forall {rep1} {rep2}. TYPE rep1 -> TYPE rep2 -> Type
type (->) = FUN Many