Haskell: see Type of value at compile time

I am wondering if there is a good way to refer to value types without imposing them explicitly on the use of type in the code (and not at runtime - there is no re-checking here).

Take the following code (using Data.Vinyl ):

 {-# LANGUAGE DataKinds, TypeOperators #-} import Data.Vinyl name = Field :: "name" ::: String age = Field :: "age" ::: Int type Person = ["name" ::: String, "age" ::: Int] 

Here we have the types "name" ::: String and "age" ::: Int , repeated in two places. If we reuse fields in multiple records, this could become multiple places. Although the Person type does refer to component fields, type declarations are independent. Therefore, changing the age to represent the Float , say, requires changes in different places.

Obviously, there is no need to explicitly enter things, as they will be deduced. However, in my case, record types are returned from the parameter parser and therefore exported. Similarly, you can write the following:

 type Name = "name" ::: String name = Field :: Name type Age = "age" ::: Int age = Field :: Age type Person = [Name, Age] 

However, then this is due to another loading of type aliases and doubling the number of lines. What I would like to write is the following:

 name = Field :: "name" ::: String age = Field :: "age" ::: Int type Person = [typeof name, typeof age] 

This explicitly binds the type of a Person with the types of its fields.

Is there any way (preferably sans-TH, but I would be interested to even involve TH) to do this?

+6
source share
1 answer

It is difficult to make the function String -> [Name] -> DecsQ of the following. Too bad with ghc7.6 (at least), checking for synonyms such as synonyms seems to stop nicer type Person = $(listOfT ['name, 'age]) from development.

 {-# LANGUAGE DataKinds, TemplateHaskell, TypeOperators #-} import Language.Haskell.TH import Control.Applicative import Data.Vinyl name = Field :: "name" ::: String age = Field :: "age" ::: Int let listOfT (n:ns) = do VarI _ ty _ _ <- reify n (appT promotedConsT) (return ty) `appT` listOfT ns listOfT [] = promotedNilT in return <$> tySynD (mkName "Person") [] (listOfT ['name, 'age]) 
0
source

All Articles