Last active
March 20, 2016 18:36
-
-
Save AndrasKovacs/340cf0300a80d3d4ec66 to your computer and use it in GitHub Desktop.
HLists backed by contiguous data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# language | |
FlexibleInstances, UndecidableInstances, MagicHash, | |
PatternSynonyms, GADTs, TypeFamilies, ScopedTypeVariables, TypeOperators, | |
DataKinds, ViewPatterns, RoleAnnotations, RankNTypes, ConstraintKinds #-} | |
import GHC.Prim | |
import Data.Vector (Vector) | |
import qualified Data.Vector as V | |
import Data.Proxy | |
import Text.Show | |
-- Naturally, we should export the patterns but not View and the Tuple | |
-- constructor | |
type role Tuple representational | |
newtype Tuple (ts :: [*]) = Tuple (Vector Any) | |
data View (ts :: [*]) where | |
Nil_ :: View '[] | |
Cons_ :: t -> Tuple ts -> View (t ': ts) | |
view :: Tuple ts -> View ts | |
view t@(Tuple v) | |
| V.null v = unsafeCoerce# Nil_ | |
| otherwise = unsafeCoerce# (Cons_ (V.unsafeHead v) (Tuple (V.unsafeTail v))) | |
pattern Nil <- (view -> Nil_) where | |
Nil = Tuple V.empty | |
pattern (:>) x xs <- (view -> Cons_ x xs) where | |
x :> (Tuple xs) = Tuple (V.cons (unsafeCoerce# x) xs) | |
infixr 5 :> | |
type family AllC c xs :: Constraint where | |
AllC c '[] = () | |
AllC c (x ': xs) = (c x, AllC c xs) | |
hmap :: AllC c ts => Proxy c -> (forall x. c x => x -> r) -> Tuple ts -> [r] | |
hmap p f Nil = [] | |
hmap p f (x :> xs) = f x : hmap p f xs | |
instance AllC Show ts => Show (Tuple ts) where | |
showsPrec _ = showListWith (++) . hmap (Proxy :: Proxy Show) show | |
foo = 0 :> False :> "foo" :> [0..5] :> Nil | |
{- Additional ideas: | |
- safe indexing with {-# language TypeApplications #-} and TypeLits | |
index foo @2 -- returns "foo" | |
- Reimplement usual hlist operations | |
- Implement append, slice, map, etc. more efficiently than with (:>) | |
- Optionally: use Seq-s or other functional vectors as underlying data instead of Vector | |
--> or use primitive "data Tuple ts = Tuple !Int# !(Array# Any)" for a bit better space efficiency | |
than Vector | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment