为何无法构造Symbol类型的单例列表?
为什么GHCi中
["A"] :: [Symbol]报错但["A", "B"]正常? 这是GHC的语法歧义导致的问题,具体原因和解决办法如下:
问题复现
$ ghci > :m +GHC.Types > :set -XDataKinds -XKindSignatures GHC.Types> :kind! (["A", "B"] :: [Symbol]) (["A", "B"] :: [Symbol]) :: [Symbol] = '["A", "B"] GHC.Types> :kind! (["A"] :: [Symbol]) <interactive>:1:2: error: * Expected kind `[Symbol]', but `["A"]' has kind `*' * In the type `(["A"] :: [Symbol])' <interactive>:1:3: error: * Expected a type, but `"A"' has kind `Symbol' * In the type `(["A"] :: [Symbol])'
原因解析
启用DataKinds后,GHC会自动把值层面的构造器提升到类型层面,但单元素列表["A"]存在语法歧义:
- GHC默认会将
["A"]解析为值层面的单元素字符串列表,它的类型是[String],属于*kind(普通类型的kind) - 而双元素列表
["A", "B"]因为结构更明确,GHC能识别出这是要被提升到类型层面的[Symbol]列表,不会和值层面的列表混淆
解决办法
有几种方式可以消除这个歧义:
- 显式添加单引号标记类型级构造
直接用'["A"]明确告诉GHC这是类型层面的列表:
GHC.Types> :kind! ('["A"] :: [Symbol]) ('["A"] :: [Symbol]) :: [Symbol] = '["A"]
- 借助
Proxy类型明确上下文
通过Proxy的类型注解让GHC确定要解析的是类型级列表:
GHC.Types> import Data.Proxy GHC.Types> :kind! Proxy :: Proxy '["A"] Proxy :: Proxy '["A"] :: Proxy '["A"] = Proxy
- 启用
-XOverloadedLists扩展
这个扩展可以让GHC更灵活地解析列表字面量,配合明确的类型注解即可正常工作:
GHC.Types> :set -XOverloadedLists GHC.Types> :kind! (["A"] :: [Symbol]) (["A"] :: [Symbol]) :: [Symbol] = '["A"]
内容的提问来源于stack exchange,提问作者David Fox
相关产品推荐
相关产品推荐

