Reputation: 3285
The module GHC.TypeLits currently provides natVal
and symbolVal
, which allow us to get a runtime value from a type of kind Nat
or Symbol
. Is there a way to get a runtime value of type [String]
out of a type of kind '[Symbol]
? I can't see an obvious way to do this. I can think of one that uses a typeclass with OverlappingInstances
, but it seems like GHC should already have a function for this.
Upvotes: 5
Views: 696
Reputation: 483
I suggest to use singletons
library. You have all that you need but using Sing
instead of Proxy
type:
$ 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]
Upvotes: 2
Reputation: 24166
symbolVal
can be mapped onto type level lists. To do so we'll need ScopedTypeVariables
and PolyKinds
in addition to DataKinds
and TypeOperators
.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PolyKinds #-}
import Data.Proxy
import GHC.TypeLits
We'll defined the class of types (of any kind) for which we can "get a runtime value of type [String]
".
class SymbolVals a where
symbolVals :: proxy a -> [String]
We can get a list of strings for any empty list of types.
instance SymbolVals '[] where
symbolVals _ = []
We can get a list of strings for any list of types where we can get a string for the first type and a list of strings for the remainder.
instance (KnownSymbol h, SymbolVals t) => SymbolVals (h ': t) where
symbolVals _ = symbolVal (Proxy :: Proxy h) : symbolVals (Proxy :: Proxy t)
Upvotes: 6