packages feed

swish-0.2.1: Swish/HaskellUtils/AccumulateM.hs

{-# OPTIONS -XMultiParamTypeClasses #-}
{-# OPTIONS -XFunctionalDependencies #-}
{-# OPTIONS -XFlexibleInstances #-}

--------------------------------------------------------------------------------
--  $Id: AccumulateM.hs,v 1.3 2004/01/22 19:53:46 graham Exp $
--
--  Copyright (c) 2003, G. KLYNE.  All rights reserved.
--  See end of this file for licence information.
--------------------------------------------------------------------------------
-- |
--  Module      :  AccummulateM
--  Copyright   :  (c) 2003, Graham Klyne
--  License     :  GPL V2
--
--  Maintainer  :  Graham Klyne
--  Stability   :  provisional
--  Portability :  H98
--
--  This module defines a monadic accumulator type.  The plan is that it be
--  used in conjunction with FunctorM and similar constructs to accumulate
--  some or all of the values visited.
--
--  Using a monad of type Accumulator, which wraps some type 'c' and is
--  also declared to be an instance of MonadAccum Accumulator c e, for some e,
--  then foldM can be used to accumulate values of type e with an initial
--  value of type c with the instance-supplied growVal method.
--
--  This module also declares accumulator instances for Int, Integer and list
--  datatypes.
--
--  This is all very well, but rather unnecessary:  it is just as easy, and
--  more standard (hence easier for other Haskell programmers to follow),
--  to use a state monad with a nullary return type; e.g.
--     execsState (stateMonadExpr) initialState
--  which returns the final state value.
--
--------------------------------------------------------------------------------

module Swish.HaskellUtils.AccumulateM
    ( Accumulator(..) )
where

import Control.Monad
    ( foldM )


class (Monad m) => MonadAccum m c e | m c -> e where
    growVal :: c -> e -> m c
    reapVal :: m c -> c

data Accumulator c = Accumulator c deriving (Eq, Show)

instance Monad Accumulator where
    (Accumulator v) >>= k  = k v
    return v               = Accumulator v

instance MonadAccum Accumulator Int Int where
    growVal n m             = Accumulator (n+m)
    reapVal (Accumulator n) = n

instance MonadAccum Accumulator Integer Integer where
    growVal n m             = Accumulator (n+m)
    reapVal (Accumulator n) = n

instance MonadAccum Accumulator [v] v where
    growVal vs v             = Accumulator (v:vs)
    reapVal (Accumulator vs) = vs


--  Tests
addVal :: Int -> Int -> (Accumulator Int)
addVal m n = Accumulator (n+m)

testList  = [1,2,3,4,5,6] :: [Int]
testList1 = [1,2,3,4,5,6] :: [Integer]
testList2 = "plugh"

test1 = foldM addVal 0 testList
test2 = Accumulator 0
test3 = (Accumulator 0) >>= addVal 1
test4 = (Accumulator 5) >>= addVal 5
test5 = (growVal 3 :: Int -> Accumulator Int) 20
test6 = foldM growVal 0 testList  :: Accumulator Int
test7 = foldM growVal 0 testList1 :: Accumulator Integer
test8 = reapVal (foldM growVal 0  testList  :: Accumulator Int)
test9 = reapVal (foldM growVal [] testList2 :: Accumulator [Char])

test = and
    [ test1 == Accumulator 21
    , test2 == Accumulator 0
    , test3 == Accumulator 1
    , test4 == Accumulator 10
    , test5 == Accumulator 23
    , test6 == Accumulator 21
    , test7 == Accumulator 21
    , test8 == 21
    , test9 == "hgulp"
    ]

--------------------------------------------------------------------------------
--
--  Copyright (c) 2003, G. KLYNE.  All rights reserved.
--
--  This file is part of Swish.
--
--  Swish is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation; either version 2 of the License, or
--  (at your option) any later version.
--
--  Swish is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with Swish; if not, write to:
--    The Free Software Foundation, Inc.,
--    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
--
--------------------------------------------------------------------------------
-- $Source: /file/cvsdev/HaskellUtils/AccumulateM.hs,v $
-- $Author: graham $
-- $Revision: 1.3 $
-- $Log: AccumulateM.hs,v $
-- Revision 1.3  2004/01/22 19:53:46  graham
-- Sync.
--
-- Revision 1.2  2004/01/13 17:12:08  graham
-- Complete functionality of AccumulateM, using functional dependencies
-- in the MonadAccum type class.
--
-- Revision 1.1  2004/01/13 12:31:24  graham
-- Move modules from HaskellRDF to HaskellUtils project
--
-- Revision 1.2  2003/09/24 18:50:52  graham
-- Revised module format to be Haddock compatible.
--
-- Revision 1.1  2003/06/12 00:49:04  graham
-- Basic query processor runs test cases OK.
-- Proof framework compiles, not yet tested.
--