Version française
Home     About     Download     Resources     Contact us    
Browse thread
Repeat: Question about corecursive type and class types (w/ answer)
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: John Prevost <prevost@m...>
Subject: Repeat: Question about corecursive type and class types (w/ answer)
I asked this a bit ago, but didn't receive any answer.

In order to do something like restricted downcasting, I'd like to say
something equivalent to the following:

type objsum =
  | A of a
  | B of b
and class type super =
  object
    method as_objsum : objsum
    ...
  end
and class type a =
  object
    inherit super
    ...
  end
and class type b =
  object
    inherit super
    ...
  end

I was not able to do the above because you can't define a type and a
class type in the same set of and s.  I was able to do the following:

type objsum' =
  | A' of a'
  | B' of b'
and super = < to_objsum' : objsum'; ... >
and a = < to_objsum' : objsum'; ... >
and b = < to_objsum' : objsum'; ... >

This second version is rather less acceptable, since if the class type
has a large number of methods (as can occur when you're doing a bit of
inheritance), there can be problems.

I've finally discovered a way to do what I want to do--although I
think it may be possible to make it easier to define.  (I was looking
at the parser, and it didn't seem easy to make the change, though.)
Here's the workaround:

class type ['a] super =
  object
    method downcast : 'a
  end

class type ['a] a =
  object
    inherit ['a] super
    method do_a : int
  end

class type ['a] b =
  object
    inherit ['a] super
    method do_b : float
  end

type objsum =
  | A of objsum a
  | B of objsum b

And to show that it works, the following (with the above assumed):

# class test_a =
    object (s)
      method downcast = A (s :> objsum a)
      method do_a = 1
    end
  class test_b =
    object (s)
      method downcast = B (s :> objsum b)
      method do_b = 1.0
    end;;
class test_a : object method do_a : int method downcast : objsum end
class test_b : object method do_b : float method downcast : objsum end
# let ta = new test_a
  let tb = new test_b;;
val ta : test_a = <obj>
val tb : test_b = <obj>
# let ta' = (ta :> objsum super)
  let tb' = (tb :> objsum super);;
val ta' : objsum super = <obj>
val tb' : objsum super = <obj>
# ta'#do_a;;
Characters 0-3:
This expression has type objsum super
It has no method do_a
# let (A ta'3) = ta'#downcast
  let (B tb'3) = tb'#downcast;;
Characters 5-11:
Warning: this pattern-matching is not exhaustive.
Characters 34-40:
Warning: this pattern-matching is not exhaustive.
val ta'3 : objsum a = <obj>
val tb'3 : objsum b = <obj>
# ta'3#do_a;;
- : int = 1
# tb'3#do_b;;
- : float = 1