packages feed

state-plus (empty) → 0.1

raw patch · 5 files changed

+183/−0 lines, 5 filesdep +QuickCheckdep +basedep +checkerssetup-changed

Dependencies added: QuickCheck, base, checkers, mtl, state-plus

Files

+ COPYING view
@@ -0,0 +1,25 @@+Copyright (c) 2012 Boris Sukholitko+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. The names of the authors may not be used to endorse or promote products+   derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 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.+
+ Control/Monad/Trans/State/Plus.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleInstances, MultiParamTypeClasses #-}+----------------------------------------------------------------------+-- |+-- Module      :  Control.Monad.Trans.State.Plus+-- Copyright   :  (c) Boris Sukholitko 2012+-- License     :  BSD3+-- +-- Maintainer  :  boriss@gmail.com+-- Stability   :  experimental+-- +-- MonadPlus with left catch (MonadOr) for StateT.+----------------------------------------------------------------------+module Control.Monad.Trans.State.Plus (+    -- * The StatePlusT monad transformer+    StatePlusT, runStatePlusT, execStatePlusT, evalStatePlusT) where++import Control.Monad.State++-- | StatePlusT behaves similar to StateT monad transformer+newtype StatePlusT s m a = MkSPT { unSPT :: StateT (Bool, s) m a }+                                deriving (Functor, MonadTrans, MonadIO)++mzeroError :: a+mzeroError = error "StatePlusT mzero value"++instance Monad m => Monad (StatePlusT s m) where+    return = lift . return+    x >>= f = (MkSPT . StateT) go+        where go s = do+                    (a, s') <- runStateT (unSPT x) s+                    if fst s'+                            then runStateT (unSPT $ f a) s'+                            else return $ (mzeroError, s')++instance Monad m => MonadState s (StatePlusT s m) where+    get = (MkSPT . StateT) $ \s -> return (snd s, s)+    put v = (MkSPT . StateT) $ \s -> return ((), (fst s, v))++plusStates :: (a, (Bool, s)) -> (a, (Bool, s)) -> (a, (Bool, s))+plusStates (_, (False, _)) b = b+plusStates a _ = a++instance Monad m => MonadPlus (StatePlusT s m) where+    mzero = (MkSPT . StateT) $ \s -> return (mzeroError, (False, snd s))+    mplus a b = (MkSPT . StateT) go where+        go s = do+            as <- runStateT (unSPT a) s+            bs <- runStateT (unSPT b) s+            let (rr, rs) = plusStates as bs+            runStateT (return rr) rs++-- | Evaluate StatePlusT monad. In difference from runStateT it returns+-- @Nothing@ if @mzero@ has been encountered. @Just a@ otherwise.+runStatePlusT :: Monad m => StatePlusT s m a -> s -> m (Maybe a, s)+runStatePlusT sm s = do+    (v, (isOK, ss)) <- runStateT (unSPT sm) (True, s)+    return (if isOK then Just v else Nothing, ss)++-- | Execute StatePlusT monad returning resulting state+execStatePlusT :: Monad m => StatePlusT s m a -> s -> m s+execStatePlusT sm s = do+    (_, ss) <- runStatePlusT sm s+    return ss++-- | Evaluate StatePlusT monad returning resulting value. See above+-- for the semantics.+evalStatePlusT :: Monad m => StatePlusT s m a -> s -> m (Maybe a)+evalStatePlusT sm s = do+    (mb, _) <- runStatePlusT sm s+    return mb
+ Setup.hs view
@@ -0,0 +1,5 @@+module Main where++import Distribution.Simple++main = defaultMain
+ state-plus.cabal view
@@ -0,0 +1,25 @@+Name:                state-plus+Version:             0.1+License:             BSD3+License-File:        COPYING+Copyright:           Boris Sukholitko, 2012+Author:              Boris Sukholitko+Maintainer:          boriss@gmail.com+Cabal-version:       >= 1.8+Build-type:          Simple+Synopsis:            MonadPlus for StateT+Description:         Implements MonadPlus with left catch (MonadOr) for StateT.+Category:            Control++library +  build-depends:  base < 5, mtl+  ghc-options:      -Wall+  exposed-modules:  Control.Monad.Trans.State.Plus++test-suite Main+  type:            exitcode-stdio-1.0+  build-depends:   base < 5, QuickCheck, mtl, state-plus, checkers+  ghc-options:     -Wall+  hs-source-dirs:  tests+  main-is:         Main.hs+
+ tests/Main.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving #-}+import Control.Monad.Trans.State.Plus+import Test.QuickCheck (Arbitrary, arbitrary, CoArbitrary, stdArgs+                            , Args(maxSuccess), quickCheckWithResult)+import Test.QuickCheck.Function+import Control.Monad.Identity+import Control.Monad.State+import Test.QuickCheck.Classes+import Test.QuickCheck.Checkers+import Test.QuickCheck.Test (isSuccess)+import Test.QuickCheck.Property (property)+import Data.List (foldl')+import System.Exit (exitFailure)++newtype P = P Bool deriving (Eq, Arbitrary, Function, Show, CoArbitrary)+newtype SI = SI [Int] deriving (Eq, Arbitrary, Function, Show, CoArbitrary)+instance Show (StatePlusT SI Identity P) where+    show m = "StatePlus: " ++ show (runIdentity $ runStatePlusT m (SI [0]))++arbSP :: SI -> P -> Bool -> StatePlusT SI Identity P+arbSP si p b = do+    put si+    when b $ mzero+    return p++instance Arbitrary (StatePlusT SI Identity P) where+    arbitrary = do+        s <- arbitrary+        p <- arbitrary+        b <- arbitrary+        return $ arbSP s p b++extract :: StatePlusT SI Identity P -> Maybe (P, SI)+extract m = case fst res of+    Nothing -> Nothing+    Just v -> Just (v, snd res)+    where res = runIdentity $ runStatePlusT m (SI [0])++instance EqProp (StatePlusT SI Identity P) where+    a =-= b = property $ (extract a) == (extract b)++-- shamelessly copied from Checkers+checkB :: TestBatch -> IO ()+checkB (name,tests) =+  do putStrLn $ "\n" ++ name ++ ":"+     mapM_ pr tests+ where+   pr (s,p) = do putStr (padTo (width + 4) ("  "++s ++ ":"))+                 r <- quickCheckWithResult stdArgs { maxSuccess = 500 } p+                 when (not $ isSuccess r) $ exitFailure+   width    = foldl' max 0 (map (length.fst) tests)+   padTo n = take n . (++ repeat ' ')++main :: IO ()+main = do+    checkB (monad (undefined :: StatePlusT SI Identity (P, P, P)))+    checkB (monadOr (undefined :: StatePlusT SI Identity (P, P)))+