Commits

'Alexey Khudyakov  committed a9683ba

Initila commit

  • Participants

Comments (0)

Files changed (6)

+dist

File Control/Monad/Primitive/Class.hs

+{-# LANGUAGE TypeFamilies     #-}
+{-# LANGUAGE FlexibleContexts #-}
+module Control.Monad.Primitive.Class (
+    MonadPrim(..)
+  ) where
+
+import Control.Monad.ST          (ST)
+import Control.Monad.Primitive   (PrimMonad)
+import Control.Monad.Trans.Class (lift)
+import Data.Monoid               (Monoid)
+
+import Control.Monad.Trans.Cont               (ContT)
+import Control.Monad.Trans.Error              (ErrorT,Error)
+import Control.Monad.Trans.Identity           (IdentityT)
+import Control.Monad.Trans.Maybe              (MaybeT)
+import Control.Monad.Trans.Reader             (ReaderT)
+import Control.Monad.Trans.RWS.Strict    as S (RWST)
+import Control.Monad.Trans.RWS.Lazy      as L (RWST)
+import Control.Monad.Trans.State.Strict  as S (StateT)
+import Control.Monad.Trans.State.Lazy    as L (StateT)
+import Control.Monad.Trans.Writer.Strict as S (WriterT)
+import Control.Monad.Trans.Writer.Lazy   as L (WriterT)
+
+
+-- | Monads in which computation based on primitive monad (instance of
+--   'PrimMonad') could be embedded. Instances must obey following laws:
+--
+--  > liftPrim . return  = return
+--  > liftPrim (m >>= f) = liftPrim m >>= liftPrim f
+class (PrimMonad (BasePrimMonad m), Monad m) => MonadPrim m where
+  type BasePrimMonad m :: * -> *
+  liftPrim :: BasePrimMonad m a -> m a
+
+
+
+instance MonadPrim IO where
+  type BasePrimMonad IO = IO
+  liftPrim = id
+
+instance MonadPrim (ST s) where
+  type BasePrimMonad (ST s) = (ST s)
+  liftPrim = id
+
+instance MonadPrim m => MonadPrim (ContT r m) where
+  type BasePrimMonad (ContT r m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance (MonadPrim m, Error e) => MonadPrim (ErrorT e m) where
+  type BasePrimMonad (ErrorT e m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance MonadPrim m => MonadPrim (IdentityT m) where
+  type BasePrimMonad (IdentityT m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance MonadPrim m => MonadPrim (MaybeT m) where
+  type BasePrimMonad (MaybeT m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance MonadPrim m => MonadPrim (ReaderT r m) where
+  type BasePrimMonad (ReaderT r m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance (MonadPrim m, Monoid w) => MonadPrim (S.RWST r w s m) where
+  type BasePrimMonad (S.RWST r w s m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance (MonadPrim m, Monoid w) => MonadPrim (L.RWST r w s m) where
+  type BasePrimMonad (L.RWST r w s m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance MonadPrim m => MonadPrim (S.StateT s m) where
+  type BasePrimMonad (S.StateT s m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance MonadPrim m => MonadPrim (L.StateT s m) where
+  type BasePrimMonad (L.StateT s m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance (MonadPrim m, Monoid w) => MonadPrim (S.WriterT w m) where
+  type BasePrimMonad (S.WriterT w m) = BasePrimMonad m
+  liftPrim = lift . liftPrim
+
+instance (MonadPrim m, Monoid w) => MonadPrim (L.WriterT w m) where
+  type BasePrimMonad (L.WriterT w m) = BasePrimMonad m
+  liftPrim = lift . liftPrim

File Data/PrimRef.hs

+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+-- | Mutable references in moads which are instances of 'MonadPrim'.
+module Data.PrimRef (
+    -- * PrimRefs
+    PrimRef
+  , newPrimRef
+  , readPrimRef
+  , writePrimRef
+  , modifyPrimRef
+  , modifyPrimRef'
+  ) where
+
+import Control.Monad.Primitive (PrimMonad(..))
+import GHC.Base                (MutVar#,newMutVar#,readMutVar#,writeMutVar#)
+import Prelude                 (($),($!))
+
+
+-- | Mutable variable which full analog of 'Data.IORef.IORef' or
+--   'Data.STRef.STRef' but could use either of the monads.
+--   Unfortunately there's no way to convert @PrimRef@ to @STRef@ or
+--   @IORef@.
+data PrimRef m a = PrimRef (MutVar# (PrimState m) a)
+
+-- | Create new mutable variable with initial value @a@.
+newPrimRef :: PrimMonad m => a -> m (PrimRef m a)
+newPrimRef a = primitive $ \s1# ->
+  case newMutVar# a s1# of
+    (# s2#, var# #) -> (# s2#, PrimRef var# #)
+
+-- | Read value of @PrimRef@.
+readPrimRef :: PrimMonad m => PrimRef m a -> m a
+readPrimRef (PrimRef var#)
+  = primitive $ \s1# -> readMutVar# var# s1#
+
+-- | Write value to @PrimRef@.
+writePrimRef :: PrimMonad m => PrimRef m a -> a -> m ()
+writePrimRef (PrimRef var#) a
+  = primitive $ \s1# ->
+      case writeMutVar# var# a s1# of
+        s2# -> (# s2#, () #)
+
+-- | Modify content of @PrimRef@ using function.
+modifyPrimRef :: PrimMonad m => PrimRef m a -> (a -> a) -> m ()
+modifyPrimRef var f = do
+  x <- readPrimRef var
+  writePrimRef var $ f x
+
+-- | Modify content of @PrimRef@ using function and evaluate result of
+--   function application to WHNF before storing it in the variable.
+modifyPrimRef' :: PrimMonad m => PrimRef m a -> (a -> a) -> m ()
+modifyPrimRef' var f = do
+  x <- readPrimRef var
+  writePrimRef var $! f x
+Copyright (c) Aleksey Khudyakov
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE 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 AUTHORS 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.
+import Distribution.Simple
+main = defaultMain

File monad-primitive.cabal

+Name:           monad-primitive
+Version:        0.1
+Synopsis:       Type class for monad transformers stack with pirimitive base monad.
+Description:
+  Type class for for monad transformers stack with pirimitive base
+  monad and mutable references whic could use both ST and IO monads.
+
+Cabal-Version:  >= 1.6
+License:        BSD3
+License-File:   LICENSE
+Author:         Aleksey Khudyakov <alexey.skladnoy@gmail.com>
+Maintainer:     Aleksey Khudyakov <alexey.skladnoy@gmail.com>
+Homepage:       http://bitbucket.org/Shimuuar/monad-primitive
+Category:       Data
+Build-Type:     Simple
+
+source-repository head
+  type:     hg
+  location: http://bitbucket.org/Shimuuar/monad-primitive
+
+Library
+  Ghc-options:          -Wall
+  Build-Depends:
+    base         >=3 && <5,
+    transformers >=0.3,
+    primitive
+  Exposed-modules:
+    Control.Monad.Primitive.Class
+    Data.PrimRef