-- For (instance MonadReader w m => MonadReader w (MaybeT m)) in GHC 6.6:
{-# OPTIONS_GHC -fallow-undecidable-instances #-}
module Utils where
-- Copyright (c) 2006-2007, Benja Fallenstein, Tuukka Hastrup
-- This file is part of Fenfire.
--
-- Fenfire 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.
--
-- Fenfire 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 Fenfire; if not, write to the Free
-- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-- MA 02111-1307 USA
import Control.Applicative
import Control.Monad
import Control.Monad.List
import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Trans
import Control.Monad.Writer (WriterT(..), MonadWriter(..), execWriterT)
import Data.Maybe (fromMaybe)
import Data.Monoid (Monoid(..))
import qualified System.Time
-- just what the rhs says, a function from a type to itself
type Endo a = a -> a
type EndoM m a = a -> m a
type Op a = a -> a -> a
type Time = Double -- seconds since the epoch
type TimeDiff = Double -- in seconds
avg :: Fractional a => Op a
avg x y = (x+y)/2
infixl 9 !?
(!?) :: [a] -> Int -> Maybe a
l !? i | i < 0 = Nothing
| i >= length l = Nothing
| otherwise = Just (l !! i)
maybeReturn :: MonadPlus m => Maybe a -> m a
maybeReturn = maybe mzero return
returnEach :: MonadPlus m => [a] -> m a
returnEach = msum . map return
maybeDo :: Monad m => Maybe a -> (a -> m ()) -> m ()
maybeDo m f = maybe (return ()) f m
getTime :: IO Time
getTime = do (System.Time.TOD secs picosecs) <- System.Time.getClockTime
return $ fromInteger secs + fromInteger picosecs / (10**(3*4))
(&) :: Monoid m => m -> m -> m
(&) = mappend
funzip :: Functor f => f (a,b) -> (f a, f b)
funzip x = (fmap fst x, fmap snd x)
ffor :: Functor f => f a -> (a -> b) -> f b
ffor = flip fmap
for :: [a] -> (a -> b) -> [b]
for = flip map
forA2 :: Applicative f => f a -> f b -> (a -> b -> c) -> f c
forA2 x y f = liftA2 f x y
forA3 :: Applicative f => f a -> f b -> f c -> (a -> b -> c -> d) -> f d
forA3 a b c f = liftA3 f a b c
newtype Comp f g a = Comp { fromComp :: f (g a) }
instance (Functor f, Functor g) => Functor (Comp f g) where
fmap f (Comp m) = Comp (fmap (fmap f) m)
instance (Applicative f, Applicative g) => Applicative (Comp f g) where
pure = Comp . pure . pure
Comp f <*> Comp x = Comp $ forA2 f x (<*>)
newtype BreadthT m a = BreadthT { runBreadthT :: WriterT [BreadthT m ()] m a }
scheduleBreadthT :: Monad m => BreadthT m a -> BreadthT m ()
scheduleBreadthT m = BreadthT $ tell [m >> return ()]
execBreadthT :: Monad m => BreadthT m a -> m ()
execBreadthT m = do rest <- execWriterT (runBreadthT m)
when (not $ null rest) $ execBreadthT (sequence_ rest)
instance Monad m => Monad (BreadthT m) where
return = BreadthT . return
m >>= f = BreadthT (runBreadthT m >>= runBreadthT . f)
instance MonadTrans BreadthT where
lift = BreadthT . lift
instance MonadState s m => MonadState s (BreadthT m) where
get = lift $ get
put = lift . put
instance MonadWriter w m => MonadWriter w (BreadthT m) where
tell = lift . tell
listen m = BreadthT $ WriterT $ do
((x,w),w') <- listen $ runWriterT (runBreadthT m)
return ((x,w'),w)
pass m = BreadthT $ WriterT $ pass $ do
((x,f),w) <- runWriterT (runBreadthT m)
return ((x,w),f)
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
instance Monad m => Monad (MaybeT m) where
return x = MaybeT $ return (Just x)
m >>= f = MaybeT $ do x <- runMaybeT m
maybe (return Nothing) (runMaybeT . f) x
fail _ = mzero
instance MonadTrans MaybeT where
lift m = MaybeT $ do x <- m; return (Just x)
instance Monad m => MonadPlus (MaybeT m) where
mzero = MaybeT $ return Nothing
mplus m n = MaybeT $ do
x <- runMaybeT m; maybe (runMaybeT n) (return . Just) x
instance MonadReader r m => MonadReader r (MaybeT m) where
ask = lift ask
local f m = MaybeT $ local f (runMaybeT m)
instance MonadWriter w m => MonadWriter w (MaybeT m) where
tell = lift . tell
listen m = MaybeT $ do (x,w) <- listen $ runMaybeT m
return $ maybe Nothing (\x' -> Just (x',w)) x
pass m = MaybeT $ pass $ do
x <- runMaybeT m; return $ maybe (Nothing,id) (\(y,f) -> (Just y,f)) x
callMaybeT :: Monad m => MaybeT m a -> MaybeT m (Maybe a)
callMaybeT = lift . runMaybeT
instance MonadWriter w m => MonadWriter w (ListT m) where
tell = lift . tell
listen m = ListT $ do (xs,w) <- listen $ runListT m
return [(x,w) | x <- xs]
pass m = ListT $ pass $ do -- not ideal impl, but makes 'censor' work
ps <- runListT m
return $ if null ps then ([], id) else (map fst ps, snd (head ps))