Last active
November 25, 2018 21:33
-
-
Save cfhammill/a68e175b2e5ae9db76a89776cfcf158e to your computer and use it in GitHub Desktop.
Unpacking applicative records
This file contains 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
import Data.Vinyl.TypeLevel | |
import Data.Vinyl | |
import Data.Vinyl.Functor | |
import Control.Applicative (liftA2) | |
type family MapTyCon m xs where | |
MapTyCon m '[] = '[] | |
MapTyCon m (x ': xs) = m x ': MapTyCon m xs | |
type family MapTyDeCon (m :: * -> *) (xs :: [*]) where | |
MapTyDeCon m '[] = '[] | |
MapTyDeCon m ((m x) ': xs) = x ': MapTyDeCon m xs | |
class RSequence (m :: * -> *) (xs :: [*]) where | |
rsequence :: forall f. (Traversable f, Applicative m) => | |
Rec f xs -> Rec m (MapTyCon f (MapTyDeCon m xs)) | |
instance RSequence m '[] where | |
rsequence RNil = RNil | |
instance (RSequence m xs) => RSequence m ((m x) ': xs) where | |
rsequence (a :& as) = | |
sequenceA a :& rsequence @m as | |
class RJoin (m :: * -> *) (xs :: [*]) where | |
rjoin :: (Applicative m) => | |
(Rec Identity '[] -> m (Rec Identity '[])) -> | |
(forall a b c. (a -> b -> c) -> m a -> m b -> m c) -> | |
Rec m xs -> | |
m (Rec Identity xs) | |
instance RJoin m '[] where | |
rjoin f _ RNil = f RNil | |
instance (RJoin m xs) => RJoin m (x ': xs) where | |
rjoin f j (a :& as) = (j (:&)) (fmap Identity a) (rjoin @m f j as) | |
unpack :: (ys ~ MapTyCon Identity (MapTyDeCon [] xs) | |
, RSequence [] xs) => | |
Rec Identity xs -> Rec [] ys | |
unpack r = rsequence r | |
zipped :: (RJoin [] ys) => Rec [] ys -> [Rec Identity ys] | |
zipped r = rjoin repeat zipWith r | |
crossed :: (RJoin [] ys) => Rec [] ys -> [Rec Identity ys] | |
crossed r = rjoin pure liftA2 r | |
tr :: Rec Identity '[[Int], [Double], [String]] | |
tr = Identity [1,2,3] :& Identity [4,5] :& Identity ["hey", "yeah", "you"] :& RNil | |
main :: IO () | |
main = do | |
putStrLn "Cartesian product version" | |
(print . crossed . unpack) tr | |
putStrLn "Zipped version" | |
(print . zipped . unpack) tr |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment