Skip to content

Instantly share code, notes, and snippets.

@UnkindPartition
Created October 8, 2015 06:31
Show Gist options
  • Save UnkindPartition/281b6ca8d43c28d3908c to your computer and use it in GitHub Desktop.
Save UnkindPartition/281b6ca8d43c28d3908c to your computer and use it in GitHub Desktop.
{-# LANGUAGE
ScopedTypeVariables,
TemplateHaskell,
TypeFamilies,
GADTs,
KindSignatures,
DataKinds,
PolyKinds,
TypeOperators,
FlexibleContexts,
RankNTypes,
UndecidableInstances,
FlexibleInstances,
InstanceSigs,
DefaultSignatures
#-}
module FirstField (firstField) where
import Generics.SOP
import Data.Promotion.TH
import Data.Promotion.Prelude
promote [d|mapHead xs = map head xs|]
firstOfProduct :: NP I xs -> I (Head xs)
firstOfProduct (I x :* _) = I x
firstOfEach :: NS (NP I) xss -> NS I (MapHead xss)
firstOfEach (Z xs) = Z (firstOfProduct xs)
firstOfEach (S xs) = S (firstOfEach xs)
class AllEqual (xs :: [*]) where
type AllEqualTo xs :: *
reduce :: NS I xs -> AllEqualTo xs
instance {-# OVERLAPS #-} AllEqual '[a] where
type AllEqualTo '[a] = a
reduce (Z (I x)) = x
instance (AllEqual as, AllEqualTo as ~ a) => AllEqual (a ': as) where
type AllEqualTo (a ': as) = a
reduce (Z (I x)) = x
reduce (S x) = reduce x
firstField :: (Generic a, AllEqual (MapHead (Code a))) => a -> AllEqualTo (MapHead (Code a))
firstField = reduce . firstOfEach . unSOP . from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment