caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Garrigue <garrigue@kurims.kyoto-u.ac.jp>
To: brian.hurt@qlogic.com
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Variant parameterized method?
Date: Wed, 23 Jul 2003 07:06:14 +0900	[thread overview]
Message-ID: <20030723070614J.garrigue@kurims.kyoto-u.ac.jp> (raw)
In-Reply-To: <Pine.LNX.4.33.0307221457320.2041-100000@eagle.ancor.com>

From: Brian Hurt <brian.hurt@qlogic.com>

> What I want to do is write a class interface like:
> 
> class virtual ['a] foo :
> object
> 	method virtual doit : 'a
> 	method map : 'b. ('a -> 'b) -> 'b foo
> end
> 
> The map function returns a new foo (not necessarily a new member of 
> whatever derived from foo class the function is actually being called on) 
> parameterized on the variant type.

This precise type is not admissible in the ocaml type system.
In ocaml recursive types must be regular: only 'a foo may occur in the
expansion of 'a foo.

This problem is discussed in an answer to PR#1730 in the caml bug
database.
This can be solved by introducing an explicit wrapper.

I give two versions of the code: with a polymorphic reference and with
a recursive modules. They are strictly equivalent: one is not safer
than the other (at least currently).

(* polymorphic reference *)
type 'a c0 = C of < map : 'b. ('a -> 'b) -> 'b c0 >

type m = {mutable new_c : 'a. 'a -> 'a c0}
let m = {new_c = fun _ -> failwith "new_c"}

class ['a] c (x : 'a) = object
  method map : 'b. ('a -> 'b) -> 'b c0 = fun f -> m.new_c (f x)
end
let () = m.new_c <- fun x -> C (new c x)

(* recursive module *)
module rec M : sig
  class ['a] c : 'a -> object
    method map : ('a -> 'b) -> 'b M.c_t
  end
  type 'a c_t = C of 'a c
end = struct
  class ['a] c (x : 'a) = object (_ : _ #M.c)
    method map = fun f -> M.C (new M.c (f x))
  end
  type 'a c_t = C of 'a c
end

Not that the fact the result of #map is a ['b c_t] rather than a ['b
c] is not a practical problem: you can just write
  let C x' = x#map f
If you prefer a [(x#map f).c] notation, use a one-field record rather
than a one constructor sum.

If you think (as I do) that all these examples are just too
complicated in practice, there is a simpler way to go:
only define a fold method in your class, and define map itself out of
the class.

Jacques Garrigue

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


  reply	other threads:[~2003-07-22 22:06 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-07-22 20:09 Brian Hurt
2003-07-22 22:06 ` Jacques Garrigue [this message]
2003-07-22 22:34   ` Brian Hurt

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=20030723070614J.garrigue@kurims.kyoto-u.ac.jp \
    --to=garrigue@kurims.kyoto-u.ac.jp \
    --cc=brian.hurt@qlogic.com \
    --cc=caml-list@inria.fr \
    /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).