{-| Module : DeepControl.Monad Description : Enable deep level Monad programming. Copyright : (C) 2015 KONISHI Yohsuke License : BSD-style (see the LICENSE file in the distribution) Maintainer : ocean0yohsuke@gmail.com Stability : experimental Portability : --- This module enables you to program in Monad for more __deeper__ level than the usual 'Control.Monad' module expresses. You would soon realize exactly what __/more deeper level/__ means by reading the example codes in order, which are attached on the Monadx(Monad2, Monad3, etc) classes below. Note: * Though this module substitutes for monad-transform consisted of elemental(without-lambda-expression) kind of monad, however, this module is unable to substitute for monad-transform consisted of complicated(tangled-with-lambda-expression) kind of monad at all. So this module does not thoroughly make mlt(monad-transformer-library) unnessasary. The range in which this module is helpful is confined to the range that single Monad or Monad with Monadx series (namely Monad2, Monad3, etc) defines. * In my opinion the above problem is hard-wired with the ability of the compiler, that is to say GHC doesn't parse @(r->)@ or @((->) r)@ as a data constructor; thus some fundamental expressions such as @(r->)|$>@ or @fmap (r->)@ are useless. Theoretically it might be impossible though. -} module DeepControl.Monad ( module Control.Monad, -- * Level-0 -- ** bind function (-<), (>-), -- ** composite function (>->), (<-<), -- * Level-1 -- ** bind-sequence function (<<), -- * Level-2 Monad2(..), -- ** bind-sequence function (>>~), (>-==), (->==), (>-~), (->~), -- ** composite function (>==>), -- * Level-3 Monad3(..), -- ** bind-sequence function (>>-==), (->>==), (>->==) ,(>--==),(->-==), (-->==), (>>>~), (->-~), (-->~), (>>-~), (->>~), (>->~), (>--~), -- ** composite function (>===>), -- * Level-4 Monad4(..), -- ** bind-sequence function (>>>>~), -- ** composite function (>====>), -- * Level-5 Monad5(..), -- ** bind-sequence function (>>>>>~), -- ** composite function (>=====>), ) where import DeepControl.Applicative import Control.Monad -- ----------------------------------------------------------------------------- -- Level-0 functions infixl 1 -<, >- -- | Alias for @'$'@. -- -- >>> Just -< 3 -- Just 3 (-<) :: (a -> b) -> a -> b (-<) = ($) -- | The auguments-flipped function for @'-<'@. -- -- >>> 3 >- Just -- Just 3 (>-) :: a -> (a -> b) -> b (>-) = flip (-<) infixr 1 <-<, >-> -- | Alias for @'.'@. -- -- >>> ((3+) <-< (2*) <-< (1+)) -< 1 -- 7 (<-<) :: (b -> c) -> (a -> b) -> a -> c (<-<) = (.) -- | The auguments-flipped function for @'<-<'@. -- -- >>> 1 >- ((+1) >-> (*2) >-> (+3)) -- 7 (>->) :: (a -> b) -> (b -> c) -> a -> c (>->) = flip (<-<) -- ----------------------------------------------------------------------------- -- Level-1 functions infixr 1 << -- | The auguments-flipped function for @'>>'@. (<<) :: Monad m => m b -> m a -> m b (<<) = flip (>>) -- ----------------------------------------------------------------------------- -- Level-2 functions infixr 1 >==> infixr 1 >>~, >>== infixr 1 ->==, >-== infixr 1 ->~, >-~ -- | The 'Monad2' class defines the Monad functions for level-2 types @m1 (m2 a)@; such as [[a]], Maybe [a], Either () (Maybe a), a -> [b], IO [a], etc. -- -- >>> :{ -- [["a","b"]] >>== \x -> -- [[0],[1,2]] >>== \y -> -- (**:) $ x ++ show y -- :} -- [["a0","b0"],["a0","b1","b2"],["a1","a2","b0"],["a1","a2","b1","b2"]] -- -- >>> :{ -- let -- isJust (Just _) = True -- isJust _ = False -- pythagorean_triple :: [Maybe (Int, Int, Int)] -- List-Maybe Monad -- pythagorean_triple = filter isJust $ -- [1..10] >-== \x -> -- [1..10] >-== \y -> -- [1..10] >-== \z -> -- guard (x < y && x*x + y*y == z*z) ->~ -- (**:) (x,y,z) -- in pythagorean_triple -- :} -- [Just (3,4,5),Just (6,8,10)] -- -- class (Monad m2) => Monad2 m2 where -- | Bind function of level-2. (>>==) :: (Monad m1) => m1 (m2 a) -> (a -> m1 (m2 b)) -> m1 (m2 b) -- | Composite function of level-2. (>==>) :: (Monad m1, Monad2 m2) => (a -> m1 (m2 b)) -> (b -> m1 (m2 c)) -> a -> m1 (m2 c) f >==> g = \x -> f x >>== g -- | Sequence function of level-2. (>>~) :: (Monad m1, Monad2 m2) => m1 (m2 a) -> m1 (m2 b) -> m1 (m2 b) m >>~ k = m >>== \_ -> k -- | Bind-cover function made of bind @'>>=='@ and cover @'-*'@, defined as @m >-== k = (-*) m >>== k@. (>-==) :: (Monad m1, Monad2 m2) => m1 a -> (a -> m1 (m2 b)) -> m1 (m2 b) m >-== k = (-*) m >>== k -- | Bind-cover function made of bind @'>>=='@ and cover @'*-'@, defined as @m >-== k = (*-) m >>== k@. (->==) :: (Monad m1, Monad2 m2) => m2 a -> (a -> m1 (m2 b)) -> m1 (m2 b) m ->== k = (*-) m >>== k -- | Sequence-cover function made of sequence @'>>~'@ and cover @'-*'@, defined as @m >-~ k = (-*) m >>~ k@. (>-~) :: (Monad m1, Monad2 m2) => m1 a -> m1 (m2 b) -> m1 (m2 b) m >-~ k = (-*) m >>~ k -- | Sequence-cover function made of sequence @'>>~'@ and cover @'*-'@, defined as @m >-~ k = (*-) m >>~ k@. (->~) :: (Monad m1, Monad2 m2) => m2 a -> m1 (m2 b) -> m1 (m2 b) m ->~ k = (*-) m >>~ k instance Monad2 Maybe where mmv >>== f = mmv >>= \mv -> case mv of Nothing -> (*:) Nothing Just a -> f a instance Monad2 [] where mmv >>== f = mmv >>= \xs -> foldr (\x acc -> f x <$|(++)|*> acc) ((*:) []) xs instance Monad2 (Either e) where mmv >>== f = mmv >>= \mv -> case mv of Left l -> (*:) (Left l) Right r -> f r -- ----------------------------------------------------------------------------- -- Level-3 functions infixr 1 >===> infixr 1 >>>~, >>>== infixr 1 >--==, ->-==, -->==, >>-==, >->==, ->>== infixr 1 >--~, ->-~, -->~, >>-~, >->~, ->>~ -- | The 'Monad3' class defines the Monad functions for level-3 types @m1 (m2 (m3 a)@. -- -- >>> :{ -- let -- isJust (Just _) = True -- isJust _ = False -- pythagorean_triple :: IO [Maybe (Int, Int, Int)] -- IO-List-Maybe Monad -- pythagorean_triple = filter isJust |$> ( -- [1..10] ->-== \x -> -- [1..10] ->-== \y -> -- [1..10] ->-== \z -> -- guard (x < y && x*x + y*y == z*z) -->~ -- print (x,y,z) >--~ -- (***:) (x,y,z) -- ) -- in pythagorean_triple -- :} -- (3,4,5) -- (6,8,10) -- [Just (3,4,5),Just (6,8,10)] -- class (Monad m3) => Monad3 m3 where (>>>==) :: (Monad m1, Monad2 m2) => m1 (m2 (m3 a)) -> (a -> m1 (m2 (m3 b))) -> m1 (m2 (m3 b)) (>===>) :: (Monad m1, Monad2 m2, Monad3 m3) => (a -> m1 (m2 (m3 b))) -> (b -> m1 (m2 (m3 c))) -> a -> m1 (m2 (m3 c)) f >===> g = \x -> f x >>>== g (>>>~) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 (m2 (m3 a)) -> m1 (m2 (m3 b)) -> m1 (m2 (m3 b)) m >>>~ k = m >>>== \_ -> k (>--==) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 a -> (a -> m1 (m2 (m3 b))) -> m1 (m2 (m3 b)) m >--== k = (-**) m >>>== k (->-==) :: (Monad m1, Monad2 m2, Monad3 m3) => m2 a -> (a -> m1 (m2 (m3 b))) -> m1 (m2 (m3 b)) m ->-== k = (*-*) m >>>== k (-->==) :: (Monad m1, Monad2 m2, Monad3 m3) => m3 a -> (a -> m1 (m2 (m3 b))) -> m1 (m2 (m3 b)) m -->== k = (**-) m >>>== k (>>-==) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 (m2 a) -> (a -> m1 (m2 (m3 b))) -> m1 (m2 (m3 b)) m >>-== k = (--*) m >>>== k (->>==) :: (Monad m1, Monad2 m2, Monad3 m3) => m2 (m3 a) -> (a -> m1 (m2 (m3 b))) -> m1 (m2 (m3 b)) m ->>== k = (*--) m >>>== k (>->==) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 (m3 a) -> (a -> m1 (m2 (m3 b))) -> m1 (m2 (m3 b)) m >->== k = (-*-) m >>>== k (>--~) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 a -> m1 (m2 (m3 b)) -> m1 (m2 (m3 b)) m >--~ k = (-**) m >>>~ k (->-~) :: (Monad m1, Monad2 m2, Monad3 m3) => m2 a -> m1 (m2 (m3 b)) -> m1 (m2 (m3 b)) m ->-~ k = (*-*) m >>>~ k (-->~) :: (Monad m1, Monad2 m2, Monad3 m3) => m3 a -> m1 (m2 (m3 b)) -> m1 (m2 (m3 b)) m -->~ k = (**-) m >>>~ k (>>-~) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 (m2 a) -> m1 (m2 (m3 b)) -> m1 (m2 (m3 b)) m >>-~ k = (--*) m >>>~ k (->>~) :: (Monad m1, Monad2 m2, Monad3 m3) => m2 (m3 a) -> m1 (m2 (m3 b)) -> m1 (m2 (m3 b)) m ->>~ k = (*--) m >>>~ k (>->~) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 (m3 a) -> m1 (m2 (m3 b)) -> m1 (m2 (m3 b)) m >->~ k = (-*-) m >>>~ k instance Monad3 Maybe where mmmv >>>== f = mmmv >>== \mv -> case mv of Nothing -> (**:) Nothing Just a -> f a instance Monad3 [] where mmmv >>>== f = mmmv >>== \xs -> foldr (\x acc -> f x <<$|(++)|*>> acc) ((**:) []) xs instance Monad3 (Either e) where mmmv >>>== f = mmmv >>== \mv -> case mv of Left l -> (**:) (Left l) Right r -> f r -- ----------------------------------------------------------------------------- -- Level-4 functions infixr 1 >====> infixr 1 >>>>~, >>>>== -- TODO: >>>>~ class (Monad m4) => Monad4 m4 where (>>>>==) :: (Monad m1, Monad2 m2, Monad3 m3) => m1 (m2 (m3 (m4 a))) -> (a -> m1 (m2 (m3 (m4 b)))) -> m1 (m2 (m3 (m4 b))) (>====>) :: (Monad m1, Monad2 m2, Monad3 m3, Monad4 m4) => (a -> m1 (m2 (m3 (m4 b)))) -> (b -> m1 (m2 (m3 (m4 c)))) -> a -> m1 (m2 (m3 (m4 c))) f >====> g = \x -> f x >>>>== g (>>>>~) :: (Monad m1, Monad2 m2, Monad3 m3, Monad4 m4) => m1 (m2 (m3 (m4 a))) -> m1 (m2 (m3 (m4 b))) -> m1 (m2 (m3 (m4 b))) m >>>>~ k = m >>>>== \_ -> k instance Monad4 Maybe where mmmmv >>>>== f = mmmmv >>>== \mv -> case mv of Nothing -> (***:) Nothing Just a -> f a instance Monad4 [] where mmmmv >>>>== f = mmmmv >>>== \xs -> foldr (\x acc -> f x <<<$|(++)|*>>> acc) ((***:) []) xs instance Monad4 (Either e) where mmmmv >>>>== f = mmmmv >>>== \mv -> case mv of Left l -> (***:) (Left l) Right r -> f r -- ----------------------------------------------------------------------------- -- Level-5 functions infixr 1 >=====> infixr 1 >>>>>~, >>>>>== -- TODO: >>>>>~ class (Monad m5) => Monad5 m5 where (>>>>>==) :: (Monad m1, Monad2 m2, Monad3 m3, Monad4 m4) => m1 (m2 (m3 (m4 (m5 a)))) -> (a -> m1 (m2 (m3 (m4 (m5 b))))) -> m1 (m2 (m3 (m4 (m5 b)))) (>=====>) :: (Monad m1, Monad2 m2, Monad3 m3, Monad4 m4, Monad5 m5) => (a -> m1 (m2 (m3 (m4 (m5 b))))) -> (b -> m1 (m2 (m3 (m4 (m5 c))))) -> a -> m1 (m2 (m3 (m4 (m5 c)))) f >=====> g = \x -> f x >>>>>== g (>>>>>~) :: (Monad m1, Monad2 m2, Monad3 m3, Monad4 m4, Monad5 m5) => m1 (m2 (m3 (m4 (m5 a)))) -> m1 (m2 (m3 (m4 (m5 b)))) -> m1 (m2 (m3 (m4 (m5 b)))) m >>>>>~ k = m >>>>>== \_ -> k instance Monad5 Maybe where mmmmmv >>>>>== f = mmmmmv >>>>== \mv -> case mv of Nothing -> (****:) Nothing Just a -> f a instance Monad5 [] where mmmmmv >>>>>== f = mmmmmv >>>>== \xs -> foldr (\x acc -> f x <<<<$|(++)|*>>>> acc) ((****:) []) xs instance Monad5 (Either e) where mmmmmv >>>>>== f = mmmmmv >>>>== \mv -> case mv of Left l -> (****:) (Left l) Right r -> f r