为什么这两种都有相同的类型?
ghci> :k [Int]
[Int] :: *
ghci> :k [Int -> Int]
[Int -> Int] :: *
每个@ Gabriel Gonzalez有用的评论编辑。
我不理解kinds
,所以我没有很好的基础来期望上述类型在kind
中有所不同。
答案 0 :(得分:9)
好吧,我们来看看。
Int :: *
[] :: * -> *
因此,当您将Int
类型应用于[]
类型构造函数时:
[] Int :: *
这是另一种(合法的)写作方式
[Int] :: *
好的,那个非常容易。
Int :: *
(->) :: * -> * -> *
[] :: * -> *
(->) Int :: * -> *
(->) Int Int :: *
与
相同Int -> Int :: *
因此,通过与上述相同的推理,
[Int -> Int] :: *
但这是一个秘密。仔细看看[]
的种类。
[] :: * -> *
这意味着将任何类型放入不合格*
的列表中是一个编译错误。如果您确实为其提供了类似*
的内容,则结果将始终具有*
种类。
你的困惑来自不保持水平分开。许多不同类型都有相同的类型。毕竟,种类*
或多或少意味着“此类型可以具有值”。 (有一些小的例外,但它们是你必须努力工作的低级别内部事物。)如果你有一个类型的值,那么这个类型有类{{1}是一个非常好的选择。 }}
答案 1 :(得分:3)
种类*
代表具体类型。考虑具体类型的一种方法是它不采用任何类型参数。所有这些都是具体类型:
Int
Int -> Int
类型[]
具有种类* -> *
- 它采用具体类型并返回具体类型。
因此,这两者都是具体类型(即具有种类*
):
[ Int ]
[ Int -> Int ]
答案 2 :(得分:1)
简而言之,*
类意味着一种类型。任何值,甚至函数(函数都是值)Int
,[Int]
,Int -> [Int]
都有*
种类。
类似Maybe的类型实际上是类型构造函数,它们从现有类型构造一个新类型。
Maybe Int
是一种新类型,Maybe Float
另一种类型......等等。
所以Maybe
是一个超级函数,它接受一个类型(例如Int
)并返回一个新的Maybe Int
。
这就是* -> *
的含义:获取一个类型并返回一个新类型。所以Maybe
本身不是一个类型,你不能在类型签名中单独使用它,你需要Maybe a
,这是一种类型。
同样地,2-uple (,)
采用2种类型a
和b
并创建一个新版本:(a, b)
。真是太好了
* -> * -> *
等......