[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2000-09-01 (16:31) |
From: | Dave Berry <dave@k...> |
Subject: | RE: Language Design |
Given a value in a monad, e.g. IO v, how can I remove v from the Monad? Surely this would be required to seamlessly integrate stateful and functional code? Dave the ingenue. -----Original Message----- From: Jerome Vouillon [mailto:Jerome.Vouillon@inria.fr] Sent: Friday, August 25, 2000 4:42 PM To: John Max Skaller; Francois.Pottier@inria.fr Cc: caml-list@inria.fr Subject: Re: Language Design On Fri, Aug 25, 2000 at 06:16:06AM +1000, John Max Skaller wrote: > Francois Pottier wrote: > > > On Wed, Aug 23, 2000 at 03:55:36PM +1000, John Max Skaller wrote: > > > What is _actually_ required is a seamless way to integrate > > > stateful and function code: > > > > Have you thought about employing some kind of monadic type system? > > Yes, but I don't know enough to do it at the moment. > [Also, it turns out monads are not general enough to write > web services in, which puts me off a bit] I think you should really consider using monads. Here is an example. We define a value of type void to be either a continuation expecting a string or a final function that do not expect anything. type void = Cont of (string -> void) | Term of (unit -> unit) This is a procedure that does nothing. let unit : void = Term (fun () -> ()) And here is a possible implementation for read: the input string is assigned to v and then there is nothing more to do. let read (v : string ref) : void = Cont (fun s -> v := s; unit) The following combinator takes two procedures p and p' and make them be evaluated in order. let rec seq (p : void) (p': void) : void = match p, p' with Cont c, _ -> Cont (fun s -> seq (c s) p') | Term t, Cont c -> Cont (fun s -> t (); c s) | Term t, Term t' -> Term (fun () -> t (); t' ()) Finally, we have an operator to assign a value v to a reference x. let set (x : 'a ref) (v : unit -> 'a) : void = Term (fun () -> x := v ()) Now we can for instance define a procedure that reads to strings and returns their concatenation. This procedure does not need to know the actual definition of type void. let read2 x = let a = ref "" in let b = ref "" in seq (read a) (seq (read b) (set x (fun () -> !a ^ !b))) You can also use some symbols to make it more readable: let ($) = seq let (-<-) = set let read2 x = let a = ref "" in let b = ref "" in read a $ read b $ x -<- (fun () -> !a ^ !b) We can try this procedure. First we define an evaluator. It takes the input stream and a procedure call as inputs. let rec eval l p = match l, p with _, Term t -> t () | s :: r, Cont c -> eval r (c s) | _ -> ((* Stuck evaluation *)) Then we evaluate read2 when two strings "a" and "b" are given as input: let x = ref "" in eval ["a"; "b"] (read2 x); !x -- Jerome