2015-02-23 69 views
6

模块GHC.TypeLits当前提供natValsymbolVal,它们允许我们从类型NatSymbol获取运行时值。有没有办法从类型'[Symbol]中获得类型为[String]的运行时值?我看不到一个明显的方式来做到这一点。我可以想象一个使用类型为OverlappingInstances的类型类型,但好像GHC应该已经有了这个功能。将类型级别列表转换为值

+0

你有没有兴趣像'FORALL(XS :: [符号]) - > HList XS - > [字符串]'或'FORALL( xs :: [Symbol]) - > Proxy xs - > [String]'。前者很简单,后者稍简单一些(你需要在xs上有一个类型约束)。 – user2407038 2015-02-23 04:05:50

+0

我正在寻找后者。虽然我很想知道前者是如何完成的(但在我看来,那种'HList(xs ::'[Symbol])'更像是一个列表列表)。另外,我从来没有见过像这样用过的'forall'。在它量化的东西之后不应该有一段时间吗? – 2015-02-23 12:06:17

回答

7

symbolVal可以映射到类型级别列表上。为此,我们需要ScopedTypeVariablesPolyKinds以及DataKindsTypeOperators

{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE TypeOperators #-} 
{-# LANGUAGE ScopedTypeVariables #-} 
{-# LANGUAGE PolyKinds #-} 

import Data.Proxy 
import GHC.TypeLits 

我们将定义的类(任何种类的)的,我们可以“获得[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) 
+0

啊,非常好。我忘记了这不会是一个需要'OverlappingInstances'的场景,因为''[]'和'(h':t)'不会重叠。谢谢。 – 2015-02-23 19:40:49

2

我建议使用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]