From 73d73e3a91e8101b6a99836477a483d6ec281eeb Mon Sep 17 00:00:00 2001
From: Philipp Balzarek
Date: Wed, 19 May 2021 22:55:33 +0200
Subject: [PATCH] Turn ElField into a newtype (#150)
* Saves a 1 word per field
* Improves accessor performance significantly both for Rec as well as ARec
---
Data/Vinyl/Class/Method.hs | 2 +-
Data/Vinyl/Derived.hs | 2 +-
Data/Vinyl/Functor.hs | 7 +++++--
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/Data/Vinyl/Class/Method.hs b/Data/Vinyl/Class/Method.hs
index d10774a..212c72d 100644
--- a/Data/Vinyl/Class/Method.hs
+++ b/Data/Vinyl/Class/Method.hs
@@ -142,7 +142,7 @@ data FieldTyper = FieldId | FieldSnd
-- | The interpretation function of the 'FieldTyper' symbols.
type family ApplyFieldTyper (f :: FieldTyper) (a :: k) :: * where
ApplyFieldTyper 'FieldId a = a
- ApplyFieldTyper 'FieldSnd '(s, b) = b
+ ApplyFieldTyper 'FieldSnd a = Snd a
-- | A mapping of record contexts into the 'FieldTyper' function
-- space. We explicitly match on 'ElField' to pick out the payload
diff --git a/Data/Vinyl/Derived.hs b/Data/Vinyl/Derived.hs
index a1bd071..6ed7582 100644
--- a/Data/Vinyl/Derived.hs
+++ b/Data/Vinyl/Derived.hs
@@ -46,7 +46,7 @@ getField :: ElField '(s,t) -> t
getField (Field x) = x
-- | Get the label name of an 'ElField'.
-getLabel :: forall s t. ElField '(s,t) -> String
+getLabel :: forall s t. KnownSymbol s => ElField '(s,t) -> String
getLabel (Field _) = symbolVal (Proxy::Proxy s)
-- | 'ElField' is isomorphic to a functor something like @Compose
diff --git a/Data/Vinyl/Functor.hs b/Data/Vinyl/Functor.hs
index 8d66021..179fd8a 100644
--- a/Data/Vinyl/Functor.hs
+++ b/Data/Vinyl/Functor.hs
@@ -42,6 +42,7 @@ import Foreign.Storable
import GHC.Generics
import GHC.TypeLits
import GHC.Types (Type)
+import Data.Vinyl.TypeLevel (Snd)
{- $introduction
This module provides functors and functor compositions
@@ -107,8 +108,10 @@ newtype Const (a :: *) (b :: k)
-- | A value with a phantom 'Symbol' label. It is not a
-- Haskell 'Functor', but it is used in many of the same places a
-- 'Functor' is used in vinyl.
-data ElField (field :: (Symbol, Type)) where
- Field :: KnownSymbol s => !t -> ElField '(s,t)
+--
+-- Morally: newtype ElField (s, t) = Field t
+-- But GHC doesn't allow that
+newtype ElField (t :: (Symbol, Type)) = Field (Snd t)
deriving instance Eq t => Eq (ElField '(s,t))
deriving instance Ord t => Ord (ElField '(s,t))