module Data.Vinyl.Core where
import Data.Vinyl.TyFun
import Control.Applicative
import Data.Monoid
import Data.Vinyl.Idiom.Identity
import Foreign.Ptr (castPtr, plusPtr)
import Foreign.Storable (Storable(..))
data Rec (el :: TyFun u * -> *) (f :: * -> *) (rrs :: [u]) where
RNil :: Rec el f '[]
(:&) :: !(f (el $ r)) -> !(Rec el f rs) -> Rec el f (r ': rs)
infixr :&
(=:) :: Applicative f => sing k -> el $ k -> Rec el f '[ k ]
_ =: x = pure x :& RNil
(<-:) :: sing r -> f (el $ r) -> Rec el f '[r]
_ <-: x = x :& RNil
infixr 6 <-:
withUniverse :: (forall x. el x) -> Rec el f rs -> Rec el f rs
withUniverse _ x = x
instance Monoid (Rec el f '[]) where
mempty = RNil
RNil `mappend` RNil = RNil
instance (Monoid (el $ r), Monoid (Rec el f rs), Applicative f) => Monoid (Rec el f (r ': rs)) where
mempty = pure mempty :& mempty
(x :& xs) `mappend` (y :& ys) = liftA2 mappend x y :& (xs `mappend` ys)
instance Eq (Rec el f '[]) where
_ == _ = True
instance (Eq (f (el $ r)), Eq (Rec el f rs)) => Eq (Rec el f (r ': rs)) where
(x :& xs) == (y :& ys) = (x == y) && (xs == ys)
instance Storable (Rec el Identity '[]) where
sizeOf _ = 0
alignment _ = 0
peek _ = return RNil
poke _ RNil = return ()
instance (Storable (el $ r), Storable (Rec el Identity rs)) => Storable (Rec el Identity (r ': rs)) where
sizeOf _ = sizeOf (undefined :: el $ r) + sizeOf (undefined :: Rec el Identity rs)
alignment _ = alignment (undefined :: el $ r)
peek ptr = do !x <- peek (castPtr ptr)
!xs <- peek (ptr `plusPtr` sizeOf (undefined :: el $ r))
return $ Identity x :& xs
poke ptr (Identity !x :& xs) = poke (castPtr ptr) x >>
poke (ptr `plusPtr` sizeOf (undefined :: el $ r)) xs