我想知道是否有一种很好的方式来引用值类型而不使用代码中的type
显式别名它们(不是在运行时 - 这里没有进行任何设置)。 / p>
使用以下代码(使用Data.Vinyl):
{-# LANGUAGE DataKinds, TypeOperators #-}
import Data.Vinyl
name = Field :: "name" ::: String
age = Field :: "age" ::: Int
type Person = ["name" ::: String, "age" ::: Int]
我们在两个地方重复了"name" ::: String
和"age" ::: Int
类型。如果我们在多个记录中重用字段,这可能会变成多个位置。尽管Person
类型实际上引用到组成字段,但类型声明是独立的。因此,将age
更改为由Float
表示,需要在各个地方进行更改。
显然,没有必要明确地输入内容,因为它们会被推断出来。但是,在我的情况下,记录类型是从选项解析器返回的,因此导出。同样,人们可以写下以下内容:
type Name = "name" ::: String
name = Field :: Name
type Age = "age" ::: Int
age = Field :: Age
type Person = [Name, Age]
然而,这涉及另一种类型别名的加载和行数的两倍。我喜欢能够写的内容如下:
name = Field :: "name" ::: String
age = Field :: "age" ::: Int
type Person = [typeof name, typeof age]
这明确地将Person
的类型链接到其字段的类型。
有没有办法(最好是sans-TH,但我甚至感兴趣甚至涉及TH)这样做?
答案 0 :(得分:0)
使用String -> [Name] -> DecsQ
函数应该很容易
下列。使用ghc7.6(至少)太糟糕了,检查类型中的循环
同义词似乎阻止了更漂亮的type Person = $(listOfT ['name, 'age])
锻炼。
{-# LANGUAGE DataKinds, TemplateHaskell, TypeOperators #-}
import Language.Haskell.TH
import Control.Applicative
import Data.Vinyl
name = Field :: "name" ::: String
age = Field :: "age" ::: Int
let listOfT (n:ns) = do
VarI _ ty _ _ <- reify n
(appT promotedConsT) (return ty) `appT` listOfT ns
listOfT [] = promotedNilT
in return <$> tySynD (mkName "Person") [] (listOfT ['name, 'age])