Skip to content

Instantly share code, notes, and snippets.

@AndrasKovacs
Last active March 20, 2016 18:36
Show Gist options
  • Save AndrasKovacs/340cf0300a80d3d4ec66 to your computer and use it in GitHub Desktop.
Save AndrasKovacs/340cf0300a80d3d4ec66 to your computer and use it in GitHub Desktop.
HLists backed by contiguous data
{-# 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