Andrew Thaddeus Martin
Andrew Thaddeus Martin

Reputation: 3285

Convert Type Level List to a Value

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

Answers (2)

Dmitry Olshansky
Dmitry Olshansky

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

Cirdec
Cirdec

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

Related Questions