@@ -3,11 +3,14 @@
3{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE RankNTypes #-}
4{-# LANGUAGE RankNTypes #-}
5{-# LANGUAGE DeriveGeneric #-}
5{-# LANGUAGE DeriveGeneric #-}
6+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7+{-# OPTIONS_GHC -funfolding-creation-threshold=100000 #-}
6module Data.Profunctor.Extra where
8module Data.Profunctor.Extra where
8import Data.Profunctor
10import Data.Profunctor
9import GHC.Generics
11import GHC.Generics
10import Debug.Trace
12import Debug.Trace
13+import Boggle hiding ((<.>))
13-- Pull dimaps to left and rights to right
16-- Pull dimaps to left and rights to right
@@ -365,7 +368,7 @@ specRightFreeTheorem = ravelRightFreeTheorem testRightFreeTheorem
365------------------------------------------------------------------------------
368------------------------------------------------------------------------------
366-- A partial dimap fusion pass which only fuses functions such that
369-- A partial dimap fusion pass which only fuses functions such that
367-- we still have an EitherFun in the 2nd argument of dimap.
370-- we still have an EitherFun in the 2nd argument of dimap.
369data PartialFusion p a b where
372data PartialFusion p a b where
370 PFDMap :: Fun c a -> Fun b d -> p a b -> PartialFusion p c d
373 PFDMap :: Fun c a -> Fun b d -> p a b -> PartialFusion p c d
371 PFDirty :: p a b -> PartialFusion p a b
374 PFDirty :: p a b -> PartialFusion p a b
@@ -408,7 +411,7 @@ ravelPartialFusion l pab = lowerPartialFusion (l (liftPartialFusion pab))
409specPartialFusion :: (MProfunctor p, MRight p) => p Int Int -> p Int Int
412specPartialFusion :: (MProfunctor p, MRight p) => p Int Int -> p Int Int
410specPartialFusion = ravelPartialFusion testPartialFusion
413specPartialFusion = ravelPartialFusion testPartialFusion
412------------------------------------------------------------------------------
415------------------------------------------------------------------------------
413-- We also lift the function space so that we can rewrite
416-- We also lift the function space so that we can rewrite
414-- dimap f (either g h) (right r) = dimap (either g f) (either id h) (right r)
417-- dimap f (either g h) (right r) = dimap (either g f) (either id h) (right r)
@@ -482,32 +485,41 @@ class MRight p where
483-- Run each stage individually
486-- Run each stage individually
485−stage1, stage2, stage3, stage4, stage5 :: (MProfunctor p, MRight p) => (forall p . (MProfunctor p, MRight p) => p a b) -> p a b
488+stage1, stage3, stage4, stage5 :: (MProfunctor p, MRight p) => (forall p . (MProfunctor p, MRight p) => p a b) -> p a b
486stage1 = lowerDimapSyntax
489stage1 = lowerDimapSyntax
487−stage2 = lowerPartialFusion
490+--stage2 = lowerPartialFusion
488stage3 = lowerRightFreeTheorem
491stage3 = lowerRightFreeTheorem
489stage4 = lowerRightFuse
492stage4 = lowerRightFuse
490stage5 = lowerDimapK1
493stage5 = lowerDimapK1
492−ravelStage1, ravelStage2, ravelStage3, ravelStage4, ravelStage5, ravelStage3a
495+ravelStage1, ravelStage3, ravelStage4, ravelStage5, ravelStage3a
493 :: (MProfunctor p, MRight p)
496 :: (MProfunctor p, MRight p)
494 => (forall p . (MProfunctor p, MRight p) => p a b -> p s t) ->
497 => (forall p . (MProfunctor p, MRight p) => p a b -> p s t) ->
495 p a b -> p s t
498 p a b -> p s t
497ravelStage1 = ravelDimapSyntax
500ravelStage1 = ravelDimapSyntax
498−ravelStage2 = ravelPartialFusion
501+--ravelStage2 = ravelPartialFusion
499ravelStage3 = ravelRightFreeTheorem
502ravelStage3 = ravelRightFreeTheorem
500ravelStage3a = ravelDimapSyntaxFF
503ravelStage3a = ravelDimapSyntaxFF
501ravelStage4 = ravelRightFuse
504ravelStage4 = ravelRightFuse
502ravelStage5 = ravelDimapK1
505ravelStage5 = ravelDimapK1
507+newtype FusionStack p a b =
504−type FusionStack p a b = DimapSyntax (RightFuse (RightFreeTheorem p)) a b
508+ FusionStack { getFusionStack :: (DimapSyntax (RightFuse (RightFreeTheorem p)) a b) }
510+instance (MRight p, MProfunctor p) => MProfunctor (FusionStack p) where
511+ mdimap f g pab = FusionStack (mdimap f g (getFusionStack pab))
512+ {-# INLINE mdimap #-}
514+instance (MProfunctor p, MRight p) => MRight (FusionStack p) where
515+ mright pab = FusionStack (mright (getFusionStack pab))
516+ {-# INLINE mright #-}
506liftFusionStack :: MProfunctor p => p a b -> FusionStack p a b
518liftFusionStack :: MProfunctor p => p a b -> FusionStack p a b
507−liftFusionStack = liftDimapSyntax . liftRightFuse . liftRightFreeTheorem
519+liftFusionStack = FusionStack . liftDimapSyntax . liftRightFuse . liftRightFreeTheorem
509lowerFusionStack :: (MProfunctor p, MRight p) => FusionStack p a b -> p a b
521lowerFusionStack :: (MProfunctor p, MRight p) => FusionStack p a b -> p a b
510−lowerFusionStack = lowerRightFreeTheorem . lowerRightFuse . lowerDimapSyntax
522+lowerFusionStack = lowerRightFreeTheorem . lowerRightFuse . lowerDimapSyntax . getFusionStack
511{-# INLINE lowerFusionStack #-}
523{-# INLINE lowerFusionStack #-}
513ravelFusionStack :: (MProfunctor p, MRight p) =>
525ravelFusionStack :: (MProfunctor p, MRight p) =>
@@ -516,9 +528,22 @@ ravelFusionStack :: (MProfunctor p, MRight p) =>
516ravelFusionStack l pab = lowerFusionStack (l (liftFusionStack pab))
528ravelFusionStack l pab = lowerFusionStack (l (liftFusionStack pab))
517{-# INLINE ravelFusionStack #-}
529{-# INLINE ravelFusionStack #-}
531+{- This is morally correct but it doesn't optimise well,
532+- it is also pointless doing it like this as it introduces a lot of
533+- unecessary fmaps which we have to fuse together
534+ravelVLFusionStack :: (MProfunctor p, MRight p, Applicative f) =>
535+ ((WrappedVLProfunctor (Boggle f) (FusionStack p)) a b
536+ -> ((WrappedVLProfunctor (Boggle f) (FusionStack p)) s t))
537+ -> p a (f b) -> p s (f t)
538+ravelVLFusionStack l pab =
539+ (lowerFusionStack (ddimap id lowerBoggle (wrappedVLProfunctor (
540+ (l (WrappedVLProfunctor (ddimap id liftBoggle (liftFusionStack pab))))))))
541+{-# INLINE ravelVLFusionStack #-}
520−specFusionStack1 :: (MProfunctor p, MRight p) => p Int Int -> p Int Int
545+--specFusionStack1 :: (MProfunctor p, MRight p) => p Int Int -> p Int Int
521−specFusionStack1 pab = ravelFusionStack testPartialFusion pab
546+--specFusionStack1 pab = ravelFusionStack testPartialFusion pab
523specFusionStack2 :: (MProfunctor p, MRight p) => p Int Int -> p Int Int
548specFusionStack2 :: (MProfunctor p, MRight p) => p Int Int -> p Int Int
524specFusionStack2 pab = ravelFusionStack testRightFreeTheorem pab
549specFusionStack2 pab = ravelFusionStack testRightFreeTheorem pab
@@ -527,6 +552,7 @@ specFusionStack2 pab = ravelFusionStack testRightFreeTheorem pab
527-- A wrapped profunctor which we can make an instance of our classes.
552-- A wrapped profunctor which we can make an instance of our classes.
555+-- Use this adapter to get a profunctor lens
530newtype WrappedProfunctor p a b = WrappedProfunctor { wrappedProfunctor :: (p a b) }
556newtype WrappedProfunctor p a b = WrappedProfunctor { wrappedProfunctor :: (p a b) }
532instance Profunctor p => MProfunctor (WrappedProfunctor p) where
558instance Profunctor p => MProfunctor (WrappedProfunctor p) where
@@ -537,6 +563,36 @@ instance Choice p => MRight (WrappedProfunctor p) where
537 mright (WrappedProfunctor p) = WrappedProfunctor (right' p)
563 mright (WrappedProfunctor p) = WrappedProfunctor (right' p)
538 {-# INLINE mright #-}
564 {-# INLINE mright #-}
566+-- | Use this adapter to get a VL lens
567+newtype WrappedVLMProfunctor f p a b
568+ = WrappedVLMProfunctor { wrappedVLMProfunctor :: p a (f b) }
570+instance (Functor f, MProfunctor p) => MProfunctor (WrappedVLMProfunctor f p) where
571+ mdimap f g (WrappedVLMProfunctor pafb)
572+ = WrappedVLMProfunctor (mdimap f (ffmap g) pafb)
573+ {-# INLINE mdimap #-}
575+instance (Applicative f, MRight p, MProfunctor p) => MRight (WrappedVLMProfunctor f p) where
576+ mright (WrappedVLMProfunctor pafb)
577+ = WrappedVLMProfunctor (mdimap (liftFun id) (EitherFun (pure . Left) (fmap Right)) (mright pafb))
578+ {-# INLINE mright #-}
581+-- | Use this adapter to get a VL lens
582+newtype WrappedVLMProfunctor f p a b
583+ = WrappedVLMProfunctor { wrappedVLProfunctor :: p a (f b) }
585+instance (Functor f, MProfunctor p) => MProfunctor (WrappedVLMProfunctor f p) where
586+ mdimap f g (WrappedVLProfunctor pafb)
587+ = WrappedVLProfunctor (mdimap f (ffmap g) pafb)
588+ {-# INLINE mdimap #-}
590+instance (Applicative f, MRight p, MProfunctor p) => MRight (WrappedVLMProfunctor f p) where
591+ mright (WrappedVLMProfunctor pafb)
592+ = WrappedVLMProfunctor (ddimap id (either (pure . Left) (fmap Right)) (mright pafb))
593+ {-# INLINE mright #-}