理解 `Random` 的 `Kind`
Understanding `Kind` of `Random`
Maybe
,据我所知是 type constructor
,种类 * -> *
。据我了解,它需要一个类型才能产生一个类型。
ghci> :k Maybe
Maybe :: * -> *
ghci> :k Maybe Int
Maybe Int :: *
但是,下面的输出是什么意思?
ghci> :k Random
Random :: * -> Constraint
Haskell 中有一些种类。具体类型具有种类 *
,这意味着它已被完全应用,因此类型如 Int
、[String]
、IO (Maybe Int)
。然后是采用 * -> k
形式的种类,其中 k
是种类变量。这些就像 Haskell 中接受 1 个或多个参数的函数,除了 *
必须 是具体类型,它不是变量。例如
> :kind Maybe
Maybe :: * -> *
> :kind Either
Either :: * -> * -> *
> data Foo a b c d e = Foo
> :kind Foo
Foo :: * -> * -> * -> * -> * -> *
然后是Constraint
种,它是由一个或多个1个其他种类构成的:
> :kind Num
Num :: * -> Constraint
> :kind Show
Show :: * -> Constraint
> import Control.Monad.State
> :kind MonadState
MonadState :: * -> (* -> *) -> Constriant
最后一个有点复杂,但可以把它想象成一个高阶函数,其中 (* -> *)
意味着第二个参数必须是一个类型构造函数,它还剩下一个类型参数。
Random
只是一个简单的类型类,因此它采用完全应用的类型并生成 Constraint
.
还有原始类型 #
,原始类型的值并融入 GHC,它们甚至需要语言扩展来解析它们的名称:
> import GHC.Prim
> :set -XMagicHash
> :i Int#
data Int#
> :k Int#
Int# :: #
大多数 Haskell 程序员永远不需要使用这些,但如果您需要为 GHC API.
进行低级编程,它们是可用的
通过一些扩展,您甚至可以自己制作类型
> :set -XDataKinds
> :set -XKindSignatures
> :set -XGADTs
> -- Multiline input in GHCi
> :set +m
> data FlagType = Flag1 | Flag2 deriving (Show)
> data Foo :: FlagType -> * -> *
| F1 :: Int -> Foo 'Flag1 Int
| F2 :: String -> Foo 'Flag2 String
|
> :t F1 1
F1 1 :: Foo 'Flag1 Int
> :t F2 "foo"
F2 "foo" :: Foo 'Flag2 String
种类为我们提供了一种类型级编程形式,可以使用它们来构建漂亮的 APIs。
可以使用很多技巧
Maybe
,据我所知是 type constructor
,种类 * -> *
。据我了解,它需要一个类型才能产生一个类型。
ghci> :k Maybe
Maybe :: * -> *
ghci> :k Maybe Int
Maybe Int :: *
但是,下面的输出是什么意思?
ghci> :k Random
Random :: * -> Constraint
Haskell 中有一些种类。具体类型具有种类 *
,这意味着它已被完全应用,因此类型如 Int
、[String]
、IO (Maybe Int)
。然后是采用 * -> k
形式的种类,其中 k
是种类变量。这些就像 Haskell 中接受 1 个或多个参数的函数,除了 *
必须 是具体类型,它不是变量。例如
> :kind Maybe
Maybe :: * -> *
> :kind Either
Either :: * -> * -> *
> data Foo a b c d e = Foo
> :kind Foo
Foo :: * -> * -> * -> * -> * -> *
然后是Constraint
种,它是由一个或多个1个其他种类构成的:
> :kind Num
Num :: * -> Constraint
> :kind Show
Show :: * -> Constraint
> import Control.Monad.State
> :kind MonadState
MonadState :: * -> (* -> *) -> Constriant
最后一个有点复杂,但可以把它想象成一个高阶函数,其中 (* -> *)
意味着第二个参数必须是一个类型构造函数,它还剩下一个类型参数。
Random
只是一个简单的类型类,因此它采用完全应用的类型并生成 Constraint
.
还有原始类型 #
,原始类型的值并融入 GHC,它们甚至需要语言扩展来解析它们的名称:
> import GHC.Prim
> :set -XMagicHash
> :i Int#
data Int#
> :k Int#
Int# :: #
大多数 Haskell 程序员永远不需要使用这些,但如果您需要为 GHC API.
进行低级编程,它们是可用的通过一些扩展,您甚至可以自己制作类型
> :set -XDataKinds
> :set -XKindSignatures
> :set -XGADTs
> -- Multiline input in GHCi
> :set +m
> data FlagType = Flag1 | Flag2 deriving (Show)
> data Foo :: FlagType -> * -> *
| F1 :: Int -> Foo 'Flag1 Int
| F2 :: String -> Foo 'Flag2 String
|
> :t F1 1
F1 1 :: Foo 'Flag1 Int
> :t F2 "foo"
F2 "foo" :: Foo 'Flag2 String
种类为我们提供了一种类型级编程形式,可以使用它们来构建漂亮的 APIs。
可以使用很多技巧