Haskell 为什么列表是*->;*?
在GHCI中,使用列表[]上的:info将显示其类型*->*Haskell 为什么列表是*->;*?,haskell,Haskell,在GHCI中,使用列表[]上的:info将显示其类型*->* Prelude> :i [] type [] :: * -> * 当我可以构造一个包含多个元素的列表时,例如[1,2,3]列表在Haskell中有特殊的语法,我如何解释这个问题 您可以使用常规语法自己定义一个数据类型,例如list,如下所示 数据列表a=Nil | Cons a(列表a) 现在特别注意,使用此定义,空列表被写入Nil而不是[],并且整数列表的类型被写入list Int而不是[Int] 如果我们看整数列表
Prelude> :i []
type [] :: * -> *
当我可以构造一个包含多个元素的列表时,例如[1,2,3]列表在Haskell中有特殊的语法,我如何解释这个问题 您可以使用常规语法自己定义一个数据类型,例如list,如下所示
数据列表a=Nil | Cons a(列表a)
现在特别注意,使用此定义,空列表被写入Nil
而不是[]
,并且整数列表的类型被写入list Int
而不是[Int]
如果我们看整数列表的类型,它由两个组件组成,List
和Int
。单独来看List
,它是一个“类型构造函数”,一个类型级别的函数,它接受一个本身是类型的参数(例如Int
),并形成一个新类型List Int
。在某些情况下,能够在不带参数的情况下谈论List
,例如作为其他类型构造函数的参数,或作为类型类的参数,例如Functor
或Applicative
,是很有用的。因此,List
具有种类*->*
,因为它需要一个参数
对于Haskell的内置列表类型,如上所述,list Int
通常被写为[Int]
,但它也可以被写为[]Int
,事实上,[]
与list
相对应,是指不应用于其参数而编写的列表类型构造函数,因此它也有种类*->*
元组类型构造函数在Haskell中也有特殊的语法。例如,整数和布尔值的一对通常写为
(Int,Bool)
,但也可以写为(,)Int Bool
,其中(,)
是未应用的对类型构造函数,并且具有种类*->*->*
,因为它需要两个参数。首先,请忘记那些*
符号。他们是历史上的怪人;Haskell正在为他们切换到名称类型
。在GHC-8.x中,您应该打开-XTypeInType
扩展以允许该操作,并打开-xnotaristype
以禁用旧语法。然后它就会读出来
> :k []
[] :: Type -> Type
这个函数箭头与列表中要放入多少元素无关,而是关于列表中应该包含哪种类型的元素,而这总是一种类型。该列表类型的列表值当然能够包含该类型的多个元素
Int ⟼ [Int] % [3], [74,12,-394], []
Bool ⟼ [Bool] % [True], repeat [False]
(Int,Bool) ⟼ [(Int,Bool)] % [(0,False)], [(3,True)]
Char ⟼ String % ['y'], "bla bla", ""
与容器相比:异构列表包含多个不同的类型(每种类型只有一个元素):
现在呢
'[Int] ⟼ HList '[Int] % HL[3], HL[-394]
'[] ⟼ HList '[] % HL[]
'[Int,String] ⟼ HList '[(Int,String)] % HL[(0,"0")], HL[(1,"one")]
命令是
:k[]
或:kind[]
[]
具有种类*->*
(或类型->类型
),因为它是一个类型构造函数,将一个类型参数作为“列表…”。例如,:k[Int]
(给定此参数的情况)具有种类*
(或类型
)。您也可以像:k([])Int
那样编写它,使[]
成为前缀构造函数,之后提供类型参数的语法更像函数应用程序,但在类型级别。这很奇怪。你们有哪个版本的ghc?也许有些“set-X…”选项有效?My:i[]
打印更有用的信息:数据[]a=[]|a:[a]--在“GHC.Types”中定义,
,然后是一些关于实例的信息。@SimonShine:您也可以在前缀中编写[]
,而不带括号:[]Int
。删除这样的语法糖分可以方便地解释列表的Monad
和Traversable
实例。
'[Int] ⟼ HList '[Int] % HL[3], HL[-394]
'[] ⟼ HList '[] % HL[]
'[Int,String] ⟼ HList '[(Int,String)] % HL[(0,"0")], HL[(1,"one")]