[project @ 1998-02-06 10:37:53 by simonm]
authorsimonm <unknown>
Fri, 6 Feb 1998 10:37:53 +0000 (10:37 +0000)
committersimonm <unknown>
Fri, 6 Feb 1998 10:37:53 +0000 (10:37 +0000)
remove stray bit of documentation - it was getting in the way of 'make boot'.

ghc/docs/simple-monad.lhs [deleted file]

diff --git a/ghc/docs/simple-monad.lhs b/ghc/docs/simple-monad.lhs
deleted file mode 100644 (file)
index 3efb2b9..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-A Simple Country Boy's Guide to Monadic-Style Programming
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Forget the category theory, forget all the fancy talk, forget "monadic
-I/O", forget Phil Wadler's papers!  Let's just do a little *plumbing*
-in the monadic style, in plain-vanilla Haskell.
-
-You can compile this guide as a Haskell module; I haven't put in
-enough code to make it run or do anytning interesting.  Excuse me for
-a moment, while I get some preliminaries out of the way...
-\begin{code}
-module Foo where
-
-infixr 9 `thenFoo`, `thenFoo_` -- ignore me
-
-data Foo = NullFoo | ConsFoo Int Foo -- assorted types, of little interest
-type SwitchChecker = String -> Bool
-type EnvA = [(String, Float)]
-type NameSupply = Int
-\end{code}
-
-*** MOTIVATION *********
-
-If you find that your Haskell functions are starting to carry around a
-lot of baggage ..., e.g.,
-\begin{code}
-f :: EnvA -> SwitchChecker -> NameSupply -> Foo -> (Int, NameSupply)
-
-f env sw_chkr names NullFoo = (0, names)
-
-f env sw_chkr names (ConsFoo x xs)
-  = let
-       (x', names')  = f env sw_chkr names  xs
-    in
-    (x + x', names')
-{-
-    `env' is some kind of environment;
-       what most people call "lookup tables".
-    `sw_chkr' is a function which, when presented with a
-       String, will tell you if that string was present
-       on the command line.
-    `names' is some kind of "name supply"; `f'
-    `f' returns a depleted name supply (2nd component of result).
--}
-\end{code}
-
-...then it may be time to use monadic code to hide some of the mess!!
-
-GRATUITOUS PLUMBING OF STATE MUST DIE.
-
-
-*** SETTING UP THE MONAD MACHINERY *******
-
-First, divide the things to be plumbed into:
-
-    * things that are only passed "downwards" through the function;
-      in the example above, the `env' and `sw_chkr' are such things;
-
-    * things that are "threaded" through the function; you want the
-      changed whatsit back from "down below"; `names' is such a thing.
-
-Now, implement your monad; let's call it `FooM'; think of a `FooM
-Wibble' as an *action* that, when performed, produces a `Wibble'.
-
-\begin{code}
-type FooM a =  EnvA            -- type of lookup-tbl being plumbed
-           -> SwitchChecker    -- type of switch looker-upper...
-           -> NameSupply       -- NameSupply going down...
-           -> (a,              -- result of the `FooM a' action
-               NameSupply)     -- NameSupply that comes back...
-\end{code}
-
-(Note: in reality, it would be good practice to hide all this stuff
-behind a clean interface, in another module.)
-
-Let's write the basic operations on these `FooM a' guys:
-
-\begin{code}
-returnFoo :: a -> FooM a
-    -- make a `FooM thing' action from a `thing' value
-    -- [Phil W would call this `unitFoo']
-
-thenFoo :: FooM a -> (a -> FooM b) -> FooM b
-    -- sequence two actions; the second uses the
-    -- result of the first
-    -- [Phil W would call this `bindFoo', or semi-colon :-]
-
-thenFoo_ :: FooM a -> FooM b -> FooM b
-    -- sequence two actions; don't care about the
-    -- result of the first
-    -- [the name is a mnemonic for "... thenFoo \ _ -> ...]
-\end{code}
-
-They're implemented in the obvious way:
-\begin{code}
-returnFoo thing env sw_chkr ns = (thing, ns)
-
-thenFoo action1 action2 env sw_chkr ns
-  = case (action1 env sw_chkr ns) of
-      (result1, ns1) -> action2 result1 env sw_chkr ns1
-
-thenFoo_ action1 action2 env sw_chkr ns
-  = case (action1 env sw_chkr ns) of
-      (_{-boring result-}, ns1) -> action2 env sw_chkr ns1
-\end{code}
-
-All those are "pure plumbing".  We need a few "monadic functions" that
-do something useful.
-
-For example, you need to be able to "do a `FooM' action" and get the
-answer back (along with the depleted NameSupply); for that, use...
-\begin{code}
-initFoo :: FooM a -> SwitchChecker -> NameSupply -> (NameSupply, a)
-
-initFoo action sw_chkr ns
-  = case (action [] sw_chkr ns) of
-      (result, new_ns) -> (new_ns, result)
-       -- gratuitous order-swapping
-\end{code}
-
-You would then have a this-monad-specific set of functions to ``reach
-down'' in the plumbing and use the env, switch-checker, etc., that are
-being carried around.  Some examples might be:
-\begin{code}
-getNewName :: FooM Int
-
-getNewName env sw_chkr ns = (ns, ns+1)
-
-------------
-
-ifSwitchSet :: String -> FooM a -> FooM a -> FooM a
-
-ifSwitchSet sw_to_chk then_ else_ env sw_chkr ns
-  = (if (sw_chkr sw_to_chk) then then_ else else_) env sw_chkr ns
-
-------------
-
-lookupInEnv :: String -> FooM Float
-
-lookupInEnv key env sw_chkr ns
-  = case [ v | (k, v) <- env, k == key ] of
-      []      -> error "lookupInEnv: no match"
-      (val:_) -> (val, ns)
-\end{code}
-
-*** USING THE MONAD MACHINERY *******
-
-We now have everything needed to write beautiful (!) monadic code.  To
-remind you of the basic "monadic" functions at our disposal:
-
-\begin{verbatim}
-returnFoo :: a -> FooM a
-thenFoo :: FooM a -> (a -> FooM b) -> FooM b
-thenFoo_ :: FooM a -> FooM b -> FooM b
-initFoo :: FooM a -> SwitchChecker -> NameSupply -> (NameSupply, a)
-
-getNewName :: FooM Int
-ifSwitchSet :: String -> FooM a -> FooM a -> FooM a
-lookupInEnv :: String -> FooM Float
-\end{verbatim}
-
-Before going on: there are a few plumbing things that aren't
-essential, but tend to be useful.  They needn't be written at the
-"bare-bones" level; they show the use of `returnFoo' and `thenFoo'.
-\begin{code}
-mapFoo :: (a -> FooM b) -> [a] -> FooM [b]
-
-mapFoo f []     = returnFoo []
-mapFoo f (x:xs)
-  = f x         `thenFoo` \ r  ->
-    mapFoo f xs `thenFoo` \ rs ->
-    returnFoo (r:rs)
-
-mapAndUnzipFoo  :: (a -> FooM (b,c))   -> [a] -> FooM ([b],[c])
-
-mapAndUnzipFoo f [] = returnFoo ([],[])
-mapAndUnzipFoo f (x:xs)
-  = f x                        `thenFoo` \ (r1,  r2)  ->
-    mapAndUnzipFoo f xs        `thenFoo` \ (rs1, rs2) ->
-    returnFoo (r1:rs1, r2:rs2)
-\end{code}
-
-You should read
-
-    f x `thenFoo` \ r -> ...
-
-as
-
-    "do `f' with argument `x', giving result `r'".
-
-If you wanted, you could do really horrible things with the C
-pre-processor (GHC and HBC let you do this...):
-\begin{verbatim}
-#define RETN returnFoo
-#define BIND {--}
-#define _TO_ `thenFoo` \ {--}
-
-mapFoo f [] = RETN []
-mapFoo f (x:xs)
-  = BIND (f x)         _TO_ r  ->
-    BIND (mapFoo f xs) _TO_ rs ->
-    RETN (r:rs)
-\end{verbatim}
-
-*** USING THE MONAD MACHINERY, FOR REAL *******
-
-We can finally re-write our `f' function in a "monadic style" (except
-I'll call it `g'), using the functions above.
-\begin{code}
-g :: Foo -> FooM Int
-    -- `g' has the same arguments as `f' (really), but in a different
-    -- order: just unravel the type synonyms
-
-g NullFoo = returnFoo 0
-
-g (ConsFoo x xs)
-  = g xs    `thenFoo` \ x' ->
-    returnFoo (x + x')
-\end{code}
-
-LOOK, MOM, NO GRATUITOUS PLUMBING OF STATE!
-
-OK, `g' shows how much the monadic style tidies up the plumbing, but
-it is really boring---it doesn't use any of the functions we defined
-earlier.  Here's a function that does:
-\begin{code}
-h :: Int -> FooM Integer
-
-h x
-  = getNewName `thenFoo_` -- ignore that one...
-    getNewName `thenFoo`  \ int_name ->
-
-    mapAndUnzipFoo zwonk [int_name ..]
-               `thenFoo` \ (some_nums, more_nums) ->
-
-    ifSwitchSet "-beat-hbc" (
-       returnFoo (toInteger (some_nums !! 6) + 42)
-
-    ) {-else-} (
-       lookupInEnv "-ghc-is-cool"  `thenFoo` \ ghc_float ->
-       returnFoo (toInteger (truncate ghc_float))
-    )
-  where
-    zwonk :: Int -> FooM (Int, Int)
-    zwonk i = returnFoo (i, x*i)
-\end{code}
-
-*** CONCLUSION *******
-
-Ordinary Haskell programming, but in a "monadic style", is a good way
-to control the plumbing of state through your code.
-
-I have left out lots and lots of Neat Things you can do with monads --
-see the papers for more interesting stuff.  But 99% of the monadic
-code you're likely to write or see will look like the stuff in here.
-
-Comments, suggestions, etc., to me, please.
-
-Will Partain
-partain@dcs.gla.ac.uk
-
-% compile with:
-%   ghc -cpp <other-flags> Foo.lhs
-%   hbc -M <other-flags> Foo.lhs