有没有办法使用'[Foo, Bar, Maybe Quux]
语法构建类型级别列表?
可以这样做:
promotedTypeList :: [Q Type] -> Q Type
promotedTypeList [] = promotedNilT
promotedTypeList (t:ts) = [t| $promotedConsT $t $(promotedTypeList ts) |]
但这会导致非常丑陋的黑线鳕:
type Example = (:) [*] ((:) * Foo ((:) * Bar ((:) * (Maybe Quux) ([] *)))) ([] [*])
编辑:
Haddock / GHC足够智能打印类型(几乎)用户输入的方式:
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
module T (Foo, Bar) where
type Foo = Int ': Bool ': Char ': '[]
type Bar = '[ Int, Bool, Char ]
显示问题的最小示例位于https://gist.github.com/phadej/f92e84a1f03ffb414ab4
答案 0 :(得分:2)
事实证明,当您按照编写函数promotedTypeList
编写函数时,TH会在提升类型列表中错误地进行拼接。换句话说,该函数生成列表的不同表示,而不是直接创建和拼接类型级别列表。这是一个简单的测试来看到这一点。
首先定义TH函数:
{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeOperators #-}
module TH where
import Language.Haskell.TH
typeList0, typeList1 :: [Q Type] -> Q Type
typeList0 = foldr (\x xs -> appT (appT promotedConsT x) xs) promotedNilT
typeList1 = foldl (\xs x -> [t| $x ': $xs |]) promotedNilT T
有两种变体 - 一种是你想要的,另一种不是。要准确了解原因,您可以查看拼接:
{-# LANGUAGE QuasiQuotes, TemplateHaskell, DataKinds, TypeOperators #-}
{-# OPTIONS -ddump-splices #-}
module Test where
import Language.Haskell.TH (stringE, Type(..))
import TH (typeList0, typeList1)
ex1 = $(typeList0 (map (return.ConT) [ ''Int, ''Bool, ''Char ]) >>= stringE . show)
ex2 = $(typeList1 (map (return.ConT) [ ''Int, ''Bool, ''Char ]) >>= stringE . show)
type Ex1 = $(typeList0 (map (return.ConT) [ ''Int, ''Bool, ''Char ]))
type Ex2 = $(typeList1 (map (return.ConT) [ ''Int, ''Bool, ''Char ]))
使用haddock -h Test.hs TH.hs
得到(有趣的位)
Test.hs:12:9-82: Splicing expression
typeList0 (map (return . ConT) [''Int, ''Bool, ''Char])
>>= stringE . show
======>
"AppT (AppT PromotedConsT (ConT GHC.Types.Int)) (AppT (AppT PromotedConsT (ConT GHC.Types.Bool)) (AppT (AppT PromotedConsT (ConT GHC.Types.Char)) PromotedNilT))"
Test.hs:13:9-82: Splicing expression
typeList1 (map (return . ConT) [''Int, ''Bool, ''Char])
>>= stringE . show
======>
"AppT (AppT (PromotedT GHC.Types.:) (ConT GHC.Types.Char)) (AppT (AppT (PromotedT GHC.Types.:) (ConT GHC.Types.Bool)) (AppT (AppT (PromotedT GHC.Types.:) (ConT GHC.Types.Int)) PromotedNilT))"
正如您可以清楚地看到的那样,两者只有不同的表示。后一种表示将提升的列表构造函数编码为PromotedT
构造函数对正常列表构造函数的应用。我猜Haddock根本无法解决这个问题。
结果如下