Haskell:在编译时引用值的类型

Imp*_*ive 6 haskell types vinyl

我想知道是否有一种很好的方式来引用值的类型而没有type在代码中使用显式别名(不是在运行时 - 这里没有进行任何验证).

请使用以下代码(使用Data.Vinyl):

{-# LANGUAGE DataKinds, TypeOperators #-}

import Data.Vinyl

name = Field :: "name" ::: String
age = Field :: "age" ::: Int
type Person = ["name" ::: String, "age" ::: Int]
Run Code Online (Sandbox Code Playgroud)

这里我们有两种类型,"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]
Run Code Online (Sandbox Code Playgroud)

然而,这涉及另一种类型别名的加载和行数的两倍.我会希望能够写出如下:

name = Field :: "name" ::: String
age = Field :: "age" ::: Int
type Person = [typeof name, typeof age]
Run Code Online (Sandbox Code Playgroud)

这明确地将a Person的类型链接到其字段的类型.

有没有办法(最好是sans-TH,但我有兴趣甚至涉及TH)这样做?

aav*_*ogt 0

String -> [Name] -> DecsQ使用以下内容创建一个函数应该很容易。ghc7.6 太糟糕了(至少),类型同义词中的循环检查似乎阻止了 prettiertype 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])
Run Code Online (Sandbox Code Playgroud)