Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 879
Andrew Thaddeus Martin Avatar asked Feb 23 '15 03:02

Andrew Thaddeus Martin


1 Answers

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)
like image 156
Cirdec Avatar answered Sep 27 '22 17:09

Cirdec