Haskell 将类型级别列表转换为值
模块GHC.TypeLits目前提供Haskell 将类型级别列表转换为值,haskell,ghc,type-level-computation,Haskell,Ghc,Type Level Computation,模块GHC.TypeLits目前提供natVal和symbolVal,允许我们从类型Nat或Symbol获取运行时值。有没有一种方法可以从类型'[Symbol]中获取类型为[String]的运行时值?我看不出一个明显的方法来做到这一点。我可以想到一个使用带有重叠实例的typeclass,但GHC似乎已经有了一个用于此的函数。可以映射到类型级列表。为此,我们需要范围类型变量和多类型以及数据类型和类型运算符 {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeOp
natVal
和symbolVal
,允许我们从类型Nat
或Symbol
获取运行时值。有没有一种方法可以从类型'[Symbol]
中获取类型为[String]
的运行时值?我看不出一个明显的方法来做到这一点。我可以想到一个使用带有重叠实例的typeclass,但GHC似乎已经有了一个用于此的函数。可以映射到类型级列表。为此,我们需要范围类型变量
和多类型
以及数据类型
和类型运算符
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PolyKinds #-}
import Data.Proxy
import GHC.TypeLits
我们将定义类型类(任何类型),我们可以“获取类型为[String]
的运行时值”
我们可以为任何类型的空列表获取字符串列表
instance SymbolVals '[] where
symbolVals _ = []
我们可以为任何类型列表获取字符串列表,其中第一种类型可以获取字符串,其余类型可以获取字符串列表
instance (KnownSymbol h, SymbolVals t) => SymbolVals (h ': t) where
symbolVals _ = symbolVal (Proxy :: Proxy h) : symbolVals (Proxy :: Proxy t)
我建议使用
singleton
库。您拥有所需的一切,但使用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]
您对
forall(xs::[Symbol])->hlistxs->[String]
或forall(xs:[Symbol])->Proxy xs->[String]
之类的内容感兴趣吗。前者比较简单,后者稍微不那么简单(在xs上需要一个类型类约束)。虽然我很想知道前者是如何实现的(但在我看来,这类HList(xs::'[Symbol])
更像是一个列表列表)。而且,我从未见过所有的都像那样使用。在它量化的东西之后不应该有一个句号吗?啊,很好。我忘了这不是一个需要重叠实例的场景,因为类型“[]
和(h):t)
不重叠。谢谢
$ 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]