packages feed

elevator (empty) → 0.1

raw patch · 4 files changed

+197/−0 lines, 4 filesdep +basedep +clean-unionsdep +transformerssetup-changed

Dependencies added: base, clean-unions, transformers

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Fumiaki Kinoshita
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Fumiaki Kinoshita nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple
+main = defaultMain
+ elevator.cabal view
@@ -0,0 +1,26 @@+name:                elevator
+version:             0.1
+synopsis:            Immediately lifts to a desired level
+description:         This package provides 'elevate' function which composes 'lift'-like transformations automatically.
+homepage:            https://github.com/fumieval/elevator
+license:             BSD3
+license-file:        LICENSE
+author:              Fumiaki Kinoshita
+maintainer:          Fumiaki Kinoshita <fumiexcel@gmail.com>
+copyright:           Copyright (C) 2014 Fumiaki Kinoshita
+category:            Data
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+source-repository head
+  type: git
+  location: https://github.com/fumieval/elevator.git
+
+library
+  exposed-modules:     Control.Elevator
+  -- other-modules:       
+  other-extensions:    TypeOperators, FlexibleContexts, FlexibleInstances, ConstraintKinds, TypeFamilies, DataKinds
+  build-depends:       base == 4.*, transformers >= 0.3, clean-unions
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+ src/Control/Elevator.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE CPP, TypeOperators, FlexibleContexts, DefaultSignatures, FlexibleInstances, ConstraintKinds, TypeFamilies, DataKinds #-}
+module Control.Elevator where
+import Control.Monad.Trans.State.Lazy as Lazy
+import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.Identity
+import Data.Functor.Identity
+import Data.OpenUnion1.Clean
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.List
+import Control.Monad.Trans.Cont
+import Data.Monoid
+import Control.Monad.ST
+
+#if MIN_VERSION_transformers(0,4,0)
+import Control.Monad.Trans.Except
+#else
+import Control.Monad.Trans.Error
+#endif
+
+class Tower f where
+  type Floors f :: List (* -> *)
+  type Floors f = Empty
+  toLoft :: Union (Floors f) a -> f a
+  default toLoft :: Union Empty a -> f a
+  toLoft = exhaust
+
+type Elevate f g = (Tower g, f ∈ Floors1 g)
+
+type Floors1 g = g :> Floors g
+
+toLoft1 :: Tower f => Union (Floors1 f) a -> f a
+toLoft1 = id ||> toLoft
+
+elevate :: Elevate f g => f a -> g a
+elevate f = (id ||> toLoft) (liftU f)
+{-# INLINE elevate #-}
+
+instance Tower IO where
+  type Floors IO = ST RealWorld :> Empty
+  toLoft = stToIO ||> exhaust
+
+instance Tower Identity
+instance Tower Maybe
+instance Tower (Either e)
+instance Tower ((->) r)
+instance Tower []
+instance Tower (ST s)
+
+instance Tower (Union u) where
+  type Floors (Union u) = u
+  toLoft = id
+
+instance (Monad m, Tower m) => Tower (Lazy.StateT s m) where
+  type Floors (Lazy.StateT s m) = Lazy.State s
+    :> Strict.State s
+    :> Strict.StateT s m
+    :> Floors1 m
+  toLoft = Lazy.state . Lazy.runState
+    ||> Lazy.state . Strict.runState
+    ||> Lazy.StateT . Strict.runStateT
+    ||> lift . toLoft1
+
+instance (Monad m, Tower m) => Tower (Strict.StateT s m) where
+  type Floors (Strict.StateT s m) = Lazy.State s
+    :> Strict.State s
+    :> Lazy.StateT s m
+    :> Floors1 m
+  toLoft = Strict.state . Lazy.runState
+    ||> Strict.state . Strict.runState
+    ||> Strict.StateT . Lazy.runStateT
+    ||> lift . toLoft1
+
+instance (Monad m, Tower m) => Tower (ReaderT r m) where
+  type Floors (ReaderT r m) = Reader r
+    :> (->) r
+    :> Floors1 m
+  toLoft = reader . runReader
+    ||> reader
+    ||> lift . toLoft1
+
+instance (Monoid w, Monad m, Tower m) => Tower (Lazy.WriterT w m) where
+  type Floors (Lazy.WriterT s m) = Lazy.Writer s
+    :> Strict.Writer s
+    :> Strict.WriterT s m
+    :> Floors1 m
+  toLoft = Lazy.writer . Lazy.runWriter
+    ||> Lazy.writer . Strict.runWriter
+    ||> Lazy.WriterT . Strict.runWriterT
+    ||> lift . toLoft1
+
+instance (Monoid w, Monad m, Tower m) => Tower (Strict.WriterT w m) where
+  type Floors (Strict.WriterT s m) = Lazy.Writer s
+    :> Strict.Writer s
+    :> Lazy.WriterT s m
+    :> Floors1 m
+  toLoft = Strict.writer . Lazy.runWriter
+    ||> Strict.writer . Strict.runWriter
+    ||> Strict.WriterT . Lazy.runWriterT
+    ||> lift . toLoft1
+
+instance (Monad m, Tower m) => Tower (ContT r m) where
+  type Floors (ContT r m) = Cont (m r)
+    :> Floors1 m
+  toLoft = (\m -> ContT $ \cont -> runCont m cont)
+    ||> lift . toLoft1
+
+instance (Monad m, Tower m) => Tower (MaybeT m) where
+  type Floors (MaybeT m) = Maybe
+    :> Floors1 m
+  toLoft = MaybeT . return
+    ||> lift . toLoft1
+
+instance (Monad m, Tower m) => Tower (ListT m) where
+  type Floors (ListT m) = []
+    :> Floors1 m
+  toLoft = ListT . return
+    ||> lift . toLoft1
+
+#if MIN_VERSION_transformers(0,4,0)
+instance (Monad m, Tower m) => Tower (ExceptT e m) where
+  type Floors (ExceptT e m) = Either e
+    :> Except e
+    :> Floors1 m
+  toLoft = ExceptT . return
+    ||> ExceptT . return . runExcept
+    ||> lift . toLoft1
+#else
+instance (Error e, Monad m, Tower m) => Tower (ErrorT e m) where
+  type Floors (ExceptT e m) = Either e
+    :> Floors1 m
+  toLoft = ErrorT . return
+    ||> lift . toLoft1
+#endif