Skip to content

Instantly share code, notes, and snippets.

@kcsongor
Created September 11, 2017 17:03
Show Gist options
  • Save kcsongor/9e0ae45c0d41e1c8aa4005742ab12182 to your computer and use it in GitHub Desktop.
Save kcsongor/9e0ae45c0d41e1c8aa4005742ab12182 to your computer and use it in GitHub Desktop.
RowToList with type families
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module RowToList where
import GHC.Generics
import Data.Kind (Type)
import GHC.TypeLits (Symbol)
import Data.Proxy (Proxy(..))
--------------------------------------------------------------------------------
-- * RowToList for Generics
type family GRowToList (rep :: Type -> Type) :: [(Symbol, Type)] where
GRowToList (l :*: r)
= GRowToList l ++ GRowToList r
GRowToList (S1 ('MetaSel ('Just name) _ _ _) (Rec0 a))
= '[ '(name, a)]
GRowToList (M1 _ m a)
= GRowToList a
GRowToList U1 = '[]
--------------------------------------------------------------------------------
-- * Utilities
type family (a :: [k]) ++ (b :: [k]) :: [k] where
'[] ++ bs = bs
(a ': as) ++ bs = a ': (as ++ bs)
--------------------------------------------------------------------------------
-- * RowToList for records (becomes just a type synyonym)
type RowToList (record :: Type) = GRowToList (Rep record)
--------------------------------------------------------------------------------
-- An example
data Tom = Tom
deriving Generic
data MyRecord = MyRecord
{ apple :: Int
, banana :: String
, orange :: Int
} deriving Generic
test :: forall record. Proxy (RowToList record)
test = Proxy
-- >>> :t test @MyRecord
-- test @MyRecord
-- :: Proxy '['("apple", Int), '("banana", [Char]), '("orange", Int)]
--
-- >>> :t test @Tom
-- test @Tom :: Proxy '[]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment