{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {- This is an exercise in learning Haskell. I wrote these mostly in a clean-room fashion as a way to figure out how to do monads, monad transformers, a Reader monad (RT) and a state monad (ST). -} module Main where import Control.Applicative import Control.Monad.Identity import Control.Monad.IO.Class import Control.Monad.Reader import Control.Monad.State import Control.Monad.Trans import Data.Monoid newtype RT r m a = RT { runRT :: r -> m a } instance Functor m => Functor (RT r m) where fmap f (RT a) = RT $ fmap f . a instance Applicative m => Applicative (RT r m) where pure = RT . const . pure (RT f) <*> (RT a) = RT $ \r -> (f r) <*> (a r) instance Monad m => Monad (RT r m) where return = pure (RT a) >>= f = RT $ \r -> do a' <- a r runRT (f a') r instance MonadTrans (RT r) where lift = RT . const instance MonadIO m => MonadIO (RT r m) where liftIO = lift . liftIO instance Monad m => MonadReader r (RT r m) where ask = RT return local t (RT a) = RT $ \r -> a (t r) type R r = RT r Identity runR :: R r a -> r -> a runR a = runIdentity . runRT a newtype ST s m a = ST { runST :: s -> m (a, s) } evalST a = fst . runST a execST a = snd . runST a instance Functor m => Functor (ST s m) where fmap f (ST a) = ST $ fmap (\(a', s') -> (f a', s')) . a instance Monad m => Applicative (ST s m) where pure a = ST $ pure . (a,) (ST f) <*> (ST a) = ST $ \s -> do ~(f', s') <- f s ~(a', s'') <- a s' return $ (f' a', s'') instance Monad m => Monad (ST s m) where return = pure (ST a) >>= f = ST $ \s -> do ~(a', s') <- (a s) runST (f a') s' instance Monad m => MonadState s (ST s m) where get = ST $ \s -> return (s, s) put s = ST $ \_ -> return ((), s) instance MonadTrans (ST s) where lift a = ST $ \s -> a >>= return . (,s) instance MonadIO m => MonadIO (ST s m) where liftIO = lift . liftIO type S s = ST s Identity runS :: S s a -> s -> (a, s) runS a = runIdentity . runST a evalS a = fst . runS a execS a = snd . runS a type RS a = RT a (S a) a runRS :: Int -> Int -> RS Int -> (Int, Int) runRS r s a = runS (runRT a r) s evalRS r s a = fst $ runRS r s a execRS r s a = snd $ runRS r s a x :: Int -> RT Int (S Int) Int x n = do r <- ask s <- lift $ do modify (+n) get return $ (n * n) + (r * s) main = print $ runS (runRT (liftA2 (+) (x 2) (x 1)) 2) 1