% % (c) The Foo Project, University of Glasgow, 1998 % % @(#) $Docid: Aug. 21th 2001 23:14 Sigbjorn Finne $ % @(#) $Contactid: sof@galconn.com $ % Basic name supply monad. \begin{code}

module NameSupply
	( NSM		-- instance {Functor,Monad} NSM
        , getNewName	-- :: NSM String
	, withNewName   -- :: String -> NSM a -> NSM a
        , getNewNames	-- :: Int -> NSM [String]
	, mapNSM
        , runNS
	) where

\end{code} %************************************************************************ %* * \subsection{Monadic plumbing for Name Supply} %* * %************************************************************************ \begin{code}

type NameSupply = [String]

newtype NSM a = NSM (NameSupply -> (a, NameSupply))

mapNSM :: (a -> b) -> NSM a -> NSM b
mapNSM f (NSM g) = NSM (\ns -> let (a, ns') = g ns in (f a, ns'))

instance Monad NSM where
  (NSM f) >>= g	= 
    NSM (\ns -> let (result1, ns1)	= f ns
                    (NSM h)		= g result1 
                in h ns1)
  return a	= NSM (\ns -> (a, ns))

getNewNames :: Int -> NSM [String]
getNewNames i = NSM (\ns -> splitAt i ns)

getNewName :: NSM String
getNewName = NSM (\ns -> (head ns, tail ns))

withNewName :: String -> NSM a -> NSM a
withNewName n (NSM f) = NSM $ \ ns ->
  case f (n:ns) of
    (v, ns') -> case ns' of
    		  (x:xs) | x == n -> (v, xs) 
		      -- make sure we remove the name added.
		  _ -> (v, ns')

runNS :: NSM a -> [String] -> a
runNS (NSM f) ns = fst (f ns)

\end{code}