caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: micha-1@fantasymail.de
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] state pattern...
Date: Tue, 28 Jun 2005 09:54:06 +0900 (JST)	[thread overview]
Message-ID: <20050628.095406.112629429.garrigue@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <200506280123.55251.micha-1@fantasymail.de>

From: Michael Wohlwend <micha-1@fantasymail.de>

> I have modified the code, so that some method(s) of the state
> classes get the context class as parameter; I think it took me 3
> hour to get the type definitions working :-)
> 
> Can this be done simpler? It works, although I don't completly
> understand all of it :-) 

There is a variety of things you could do to simplify your code.
If you want to keep the polymorphic-method based approach, you can
avoid type annotations in stat1#show an state2#show by writing
(this : #state).

But another way to simplify things is to switch to subtyping.
That is, just have
  method show : param -> unit
in class state, and change context to
  method show = state_#show (this :> param)

Note also that your definition of state as a recursive type will cause
problems later, if you try to finalize it in a class.

Here is a possibly simpler version of your code.

class type param =
 object 
 method name : string
 end

class type ['next] state =
 object
  method show: param -> unit
  method next: 'next
 end

class ['state] context s =
 object (this:'self)
 val name = "context"
 val state : _ #state = s 
 method state : 'state = state
 method name = name
 method show = state#show (this :> param)
 method run = {< state = state#next >}
 end

class state1 = object (this : _ #state)
 method show c = print_endline ("state1 of " ^ c#name)
 method next = new state2 
end
and state2 = object (this : _ #state)
 method show c = print_endline ("state2 of " ^ c#name) 
 method next = new state1
end;;

let c = new context (new state1) ;;
c#show;;
let c = c#run;;
c#show;;

Note that there is an intrinsic weakness to the object-oriented
approach in ocaml: state1 and state2 must actually be the same type,
since a method of context cannot return context with a different
parameter.

On the other hand, if you exactly know what a state should be from the
beginning, you can eliminate all type parameters.

class type param =
 object 
 method name : string
 end

class type state =
 object
  method show: param -> unit
  method next: state
 end

class context s =
 object (this)
 val name = "context"
 val state : state = s 
 method state = state
 method name = name
 method show = state#show (this :> param)
 method run = {< state = state#next >}
 end

class state1 = object (this : #state)
 method show c = print_endline ("state1 of " ^ c#name)
 method next = new state2
end
and state2 = object (this : #state)
 method show c = print_endline ("state2 of " ^ c#name) 
 method next = new state1
end;;

But then there is little point in using classes... records and
functions would do the job in a clearer way.

Jacques Garrigue


  reply	other threads:[~2005-06-28  0:53 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-06-26 19:57 Michael Wohlwend
2005-06-26 22:13 ` [Caml-list] " james woodyatt
2005-06-26 22:45   ` Michael Wohlwend
2005-06-27 23:23   ` Michael Wohlwend
2005-06-28  0:54     ` Jacques Garrigue [this message]
2005-06-28 12:24       ` Michael Wohlwend
2005-06-28 13:20         ` Jacques Garrigue

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050628.095406.112629429.garrigue@math.nagoya-u.ac.jp \
    --to=garrigue@math.nagoya-u.ac.jp \
    --cc=caml-list@yquem.inria.fr \
    --cc=micha-1@fantasymail.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).