将类型级别列表转换为值

Convert Type Level List to a Value

模块GHC.TypeLits目前提供了natValsymbolVal,它们允许我们从NatSymbol类型中获取运行时值.有没有办法从类型 '[Symbol] 中获取类型 [String] 的运行时值?我看不到一个明显的方法来做到这一点。我能想到一个使用带有 OverlappingInstances 的类型类,但似乎 GHC 应该已经有一个函数了。

symbolVal 可以映射到类型级别列表。为此,除了 DataKindsTypeOperators.

之外,我们还需要 ScopedTypeVariablesPolyKinds
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PolyKinds #-}

import Data.Proxy
import GHC.TypeLits

我们将定义 class 类型(任何类型),我们可以 "get a runtime value of type [String]"。

class SymbolVals a where
    symbolVals :: proxy a -> [String]

我们可以获得任何空类型列表的字符串列表。

instance SymbolVals '[] where
    symbolVals _ = []

我们可以获得任何类型列表的字符串列表,其中我们可以获得第一种类型的字符串和其余类型的字符串列表。

instance (KnownSymbol h, SymbolVals t) => SymbolVals (h ': t) where
    symbolVals _ = symbolVal (Proxy :: Proxy h) : symbolVals (Proxy :: Proxy t)

我建议使用 singletons 库。您拥有所需的一切,但使用 Sing 而不是 Proxy 类型:

$ stack ghci --package singletons
Configuring GHCi with the following packages: 
GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
Prelude> :set -XDataKinds 
Prelude> import Data.Singletons.Prelude
Prelude Data.Singletons.Prelude> fromSing (sing :: Sing '["a","b"])
["a","b"]
Prelude Data.Singletons.Prelude> :t fromSing (sing :: Sing '["a","b"])
fromSing (sing :: Sing '["a","b"]) :: [String]