| 1 | {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, GeneralizedNewtypeDeriving, -XNoMonomorphismRestriction #-} |
|---|
| 2 | |
|---|
| 3 | module MonadSupply |
|---|
| 4 | (SupplyT, |
|---|
| 5 | MonadSupply, |
|---|
| 6 | snext, |
|---|
| 7 | snexts, |
|---|
| 8 | Supply, |
|---|
| 9 | runSupplyT, |
|---|
| 10 | runSupply, |
|---|
| 11 | useSupply) |
|---|
| 12 | where |
|---|
| 13 | |
|---|
| 14 | import Control.Arrow |
|---|
| 15 | import Control.Monad |
|---|
| 16 | import Control.Applicative |
|---|
| 17 | import Control.Monad.State |
|---|
| 18 | import Control.Monad.Identity |
|---|
| 19 | import Data.List |
|---|
| 20 | |
|---|
| 21 | -- based on RWH's Supply monad in ch. 15: http://book.realworldhaskell.org/read/programming-with-monads.html#id646649 |
|---|
| 22 | -- transformer in ch. 18: http://book.realworldhaskell.org/read/monad-transformers.html#monadtrans.maybet |
|---|
| 23 | |
|---|
| 24 | -- advantages over previous version at http://www.haskell.org/haskellwiki/New_monads/MonadSupply |
|---|
| 25 | -- hides implementation, handles finite supplies |
|---|
| 26 | |
|---|
| 27 | newtype SupplyT s m a = ST (StateT [s] m a) deriving (Functor, Monad, MonadTrans, MonadIO) |
|---|
| 28 | newtype Supply s a = S (SupplyT s Identity a) deriving (Monad, Functor, MonadSupply s) |
|---|
| 29 | |
|---|
| 30 | class (Monad m, Functor m) => MonadSupply s m | m -> s where |
|---|
| 31 | snext :: m (Maybe s) |
|---|
| 32 | snext = head <$> snexts 1 |
|---|
| 33 | snexts :: Integral a => a -> m [Maybe s] |
|---|
| 34 | |
|---|
| 35 | instance (Monad m, Functor m) => MonadSupply s (SupplyT s m) where |
|---|
| 36 | snexts n = ST $ do -- blackh @ #haskell's solution, cleaner than my Kleislis |
|---|
| 37 | (these,rest) <- genericSplitAt n <$> get |
|---|
| 38 | put rest |
|---|
| 39 | return . genericTake n $ map Just these ++ repeat Nothing |
|---|
| 40 | |
|---|
| 41 | runSupply :: Supply s a -> [s] -> (a, [s]) |
|---|
| 42 | runSupply (S m) = runIdentity . runSupplyT m |
|---|
| 43 | |
|---|
| 44 | runSupplyT :: SupplyT s m a -> [s] -> m (a, [s]) |
|---|
| 45 | runSupplyT (ST s) = runStateT s |
|---|
| 46 | |
|---|
| 47 | useSupply :: (Functor f) => Supply s a -> f [s] -> f a |
|---|
| 48 | useSupply = fmap . (fst `dot` runSupply) |
|---|
| 49 | |
|---|
| 50 | -- from http://www.haskell.org/haskellwiki/Pointfree#Dot |
|---|
| 51 | dot :: (c -> d) -> (a -> b -> c) -> a -> b -> d |
|---|
| 52 | dot = (.) . (.) |
|---|
| 53 | |
|---|
| 54 | main :: IO () |
|---|
| 55 | main = mapM_ s [1 .. 5] |
|---|
| 56 | where s = putStrLn . show |
|---|
| 57 | |
|---|
| 58 | -- mapM_ s $ useSupply main' [1 .. 5] |
|---|
| 59 | -- mapM_ s $ useSupply main' [replicate k ['a'..'z'] | k <- [1..]] |
|---|
| 60 | |
|---|
| 61 | --main' :: MonadSupply a m => m [a] |
|---|
| 62 | main' = snext |
|---|