module Data.Vinyl.Operators
( (<<$>>)
, (<<*>>)
, (<+>)
, type (++)
, RecApplicative(rpure)
, rtraverse
, rdist
, rdistLazy
, FoldRec(foldRec)
, recToList
, showWithNames
, rshow
) where
import Data.Vinyl.Core
import Data.Vinyl.Functor
import Data.Vinyl.TyFun
import Data.Vinyl.Witnesses
import Data.Vinyl.Constraint
import Data.Vinyl.Derived
import qualified Data.Vinyl.Idiom.Identity as I
import qualified Data.Vinyl.Idiom.Thunk as I
import qualified Data.Vinyl.Universe.Const as U
import Control.Applicative
import qualified Data.List as L (intercalate)
(<+>) :: Rec el f as -> Rec el f bs -> Rec el f (as ++ bs)
RNil <+> xs = xs
(x :& xs) <+> ys = x :& (xs <+> ys)
infixr 5 <+>
type family (as :: [k]) ++ (bs :: [k]) :: [k]
type instance '[] ++ bs = bs
type instance (a ': as) ++ bs = a ': (as ++ bs)
(<<$>>) :: (forall x. f x -> g x) -> Rec el f rs -> Rec el g rs
_ <<$>> RNil = RNil
eta <<$>> x :& xs = eta x :& (eta <<$>> xs)
infixl 8 <<$>>
(<<*>>) :: Rec el (Lift (->) f g) rs -> Rec el f rs -> Rec el g rs
RNil <<*>> RNil = RNil
f :& fs <<*>> x :& xs = runLift f x :& (fs <<*>> xs)
infixl 8 <<*>>
class RecApplicative rs where
rpure :: (forall x. f x) -> Rec el f rs
instance RecApplicative '[] where
rpure _ = RNil
instance RecApplicative rs => RecApplicative (f ': rs) where
rpure s = s :& rpure s
class FoldRec r a where
foldRec :: (a -> b -> b) -> b -> r -> b
instance FoldRec (Rec el f '[]) a where
foldRec _ z RNil = z
instance (t ~ (el $ r), FoldRec (Rec el f rs) (f t)) => FoldRec (Rec el f (r ': rs)) (f t) where
foldRec f z (x :& xs) = f x (foldRec f z xs)
recToList :: FoldRec (Rec el f rs) (f t) => Rec el f rs -> [f t]
recToList = foldRec (\e a -> [e] ++ a) []
rtraverse :: Applicative h => (forall x. f x -> h (g x)) -> Rec el f rs -> h (Rec el g rs)
rtraverse _ RNil = pure RNil
rtraverse f (x :& xs) = (:&) <$> f x <*> rtraverse f xs
rdist :: Applicative f => Rec el f rs -> f (PlainRec el rs)
rdist = rtraverse $ fmap I.Identity
rdistLazy :: Applicative f => Rec el f rs -> f (LazyPlainRec el rs)
rdistLazy = rtraverse $ fmap I.Thunk
showWithNames :: RecAll el f rs Show => PlainRec (U.Const String) rs -> Rec el f rs -> String
showWithNames names rec = "{ " ++ L.intercalate ", " (go names rec []) ++ " }"
where
go :: RecAll el f rs Show => PlainRec (U.Const String) rs -> Rec el f rs -> [String] -> [String]
go RNil RNil ss = ss
go (I.Identity n :& ns) (x :& xs) ss = (n ++ " =: " ++ show x) : go ns xs ss
rshow :: (Implicit (PlainRec (U.Const String) rs), RecAll el f rs Show) => Rec el f rs -> String
rshow = showWithNames implicitly