caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* recursive types
@ 2008-03-24  3:16 Jacques Le Normand
  2008-03-24  3:51 ` [Caml-list] " Erik de Castro Lopo
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Jacques Le Normand @ 2008-03-24  3:16 UTC (permalink / raw)
  To: caml-list caml-list

[-- Attachment #1: Type: text/plain, Size: 595 bytes --]

hello again list
is it possible to have mutually recursive classes and types? I'm trying to
implement the zipper, and this is what I came up with:

class type node_wrapper =
object
  method identify : string
  method get_child_location : location
end

class virtual nodeable =
object(self)
  method virtual to_node_wrapper : node_wrapper
end

type path = (nodeable list * location * nodeable list) option
and location = Loc of nodeable * path


which, of course, doesn't type check


a simpler test case would be

class a =
  val b : c
end

type c = a

thanks for all the help so far!
--Jacques

[-- Attachment #2: Type: text/html, Size: 723 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] recursive types
  2008-03-24  3:16 recursive types Jacques Le Normand
@ 2008-03-24  3:51 ` Erik de Castro Lopo
  2008-03-24  3:51 ` Erik de Castro Lopo
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: Erik de Castro Lopo @ 2008-03-24  3:51 UTC (permalink / raw)
  To: caml-list

Jacques Le Normand wrote:

> hello again list
> is it possible to have mutually recursive classes and types?

Yes and yes.

I haven't played much with classes at all, but recursive types
can be defined as :

  type x_t =
  {  x : int ; y : y_t ; }
  and
  y_t =
  { z : string }

For recursive classes I beleive that you do

   class xxx = ....

   and yyy =

to define mutually recursive classes xxx and yyy.

Erik
-- 
-----------------------------------------------------------------
Erik de Castro Lopo
-----------------------------------------------------------------
Think of XML as Lisp for COBOL programmers.
	-- Tony-A (some guy on /.)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] recursive types
  2008-03-24  3:16 recursive types Jacques Le Normand
  2008-03-24  3:51 ` [Caml-list] " Erik de Castro Lopo
@ 2008-03-24  3:51 ` Erik de Castro Lopo
  2008-03-24  8:37 ` Jeremy Yallop
  2008-03-24  9:02 ` Remi Vanicat
  3 siblings, 0 replies; 17+ messages in thread
From: Erik de Castro Lopo @ 2008-03-24  3:51 UTC (permalink / raw)
  To: caml-list

Jacques Le Normand wrote:

> hello again list
> is it possible to have mutually recursive classes and types?

Yes and yes.

I haven't played much with classes at all, but recursive types
can be defined as :

  type x_t =
  {  x : int ; y : y_t ; }
  and
  y_t =
  { z : string }

For recursive classes I beleive that you do

   class xxx = ....

   and yyy =

to define mutually recursive classes xxx and yyy.

Erik
-- 
-----------------------------------------------------------------
Erik de Castro Lopo
-----------------------------------------------------------------
Think of XML as Lisp for COBOL programmers.
	-- Tony-A (some guy on /.)
-- 
-----------------------------------------------------------------
Erik de Castro Lopo
-----------------------------------------------------------------
"Microsoft treats security vulnerabilities as public relations
problems."  -- Bruce Schneier


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] recursive types
  2008-03-24  3:16 recursive types Jacques Le Normand
  2008-03-24  3:51 ` [Caml-list] " Erik de Castro Lopo
  2008-03-24  3:51 ` Erik de Castro Lopo
@ 2008-03-24  8:37 ` Jeremy Yallop
  2008-03-24  9:02 ` Remi Vanicat
  3 siblings, 0 replies; 17+ messages in thread
From: Jeremy Yallop @ 2008-03-24  8:37 UTC (permalink / raw)
  To: Jacques Le Normand; +Cc: caml-list caml-list

Jacques Le Normand wrote:
> is it possible to have mutually recursive classes and types?

Yes, using recursive modules.  The syntax is a little heavy, though, 
since you have to write some of the definitions in both the signature 
and the implementation.

> class type node_wrapper =
> object
>   method identify : string
>   method get_child_location : location
> end
> 
> class virtual nodeable =
> object(self)
>   method virtual to_node_wrapper : node_wrapper
> end
> 
> type path = (nodeable list * location * nodeable list) option
> and location = Loc of nodeable * path

This might be written as

   module rec M :
   sig
     class type node_wrapper =
     object
       method identify : string
       method get_child_location : M.location
     end

     class virtual nodeable :
     object
       method virtual to_node_wrapper : node_wrapper
     end

     type path = (nodeable list * M.location * nodeable list) option
     type location = Loc of nodeable * path
   end =
   struct
     class type node_wrapper =
     object
       method identify : string
       method get_child_location : M.location
     end

     class virtual nodeable =
     object
       method virtual to_node_wrapper : node_wrapper
     end

     type path = (nodeable list * M.location * nodeable list) option
     type location = Loc of nodeable * path
   end

The definitions which merely define type aliases (node_wrapper and path) 
can be shortened in the implementation section if you prefer:

   module rec M :
   sig
      [elided]
   end =
   struct
     class type node_wrapper = M.node_wrapper

     class virtual nodeable =
     object
       method virtual to_node_wrapper : node_wrapper
     end

     type path = M.path
     type location = Loc of nodeable * path
   end

Jeremy.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: recursive types
  2008-03-24  3:16 recursive types Jacques Le Normand
                   ` (2 preceding siblings ...)
  2008-03-24  8:37 ` Jeremy Yallop
@ 2008-03-24  9:02 ` Remi Vanicat
  3 siblings, 0 replies; 17+ messages in thread
From: Remi Vanicat @ 2008-03-24  9:02 UTC (permalink / raw)
  To: caml-list

"Jacques Le Normand" <rathereasy@gmail.com> writes:

> hello again list
> is it possible to have mutually recursive classes and types? I'm trying to
> implement the zipper, and this is what I came up with:

Not directly, but you can use polymorphism to have it:


class type ['a] node_wrapper =
object
  method identify : string
  method get_child_location : 'a
end

class virtual ['a] nodeable =
object(self)
  method virtual to_node_wrapper : 'a node_wrapper
end

type path = (location nodeable list * location * location nodeable list) option
and location = Loc of location nodeable * path

you could even do something like :


class type ['a] pre_node_wrapper =
object
  method identify : string
  method get_child_location : 'a
end

class virtual ['a] pre_nodeable =
object(self)
  method virtual to_node_wrapper : 'a pre_node_wrapper
end

type path = (location pre_nodeable list * location * location pre_nodeable list) option
and location = Loc of location pre_nodeable * path

class type node_wrapper = [location] pre_node_wrapper

class virtual nodeable = [location] pre_nodeable

(you could also make the type polymorphic, and the class
monomorphic if you declare the type before the class and class
type). 

You probably should come on the Beginner's list, where such question
could be answered (see http://groups.yahoo.com/group/ocaml_beginners)

--
Rémi Vanicat


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-16  8:55           ` Jacques Garrigue
@ 2005-11-17  1:45             ` Keiko Nakata
  0 siblings, 0 replies; 17+ messages in thread
From: Keiko Nakata @ 2005-11-17  1:45 UTC (permalink / raw)
  To: garrigue; +Cc: caml-list

From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>

> No need to memorize equivalences: s tuple expands at its head to s * s.
> The type checker guarantees that it is always safe to expand the head
> of a type (i.e., definitions are well-founded.)

Thanks for the reply.

> In order for unification to succeed above, t must expand to
> (< m: 'a * 'a> as 'a), and s too. But to print nicely types we must
> keep the abbreviations. This is done by memoizing expansions inside 
> the abbreviations themselves. 

This is a pretty nice feature of the type checker.
When programming with polymorphic variants,
the last part of typing error messages, 
which tells me incompatibilities of types using abbreviating names,
always helps me a lot.

With best regards,
Keiko 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-16 23:00         ` Swaroop Sridhar
@ 2005-11-16 23:56           ` Swaroop Sridhar
  0 siblings, 0 replies; 17+ messages in thread
From: Swaroop Sridhar @ 2005-11-16 23:56 UTC (permalink / raw)
  To: Jacques Garrigue, caml-list

A (small) correction, I forgot to write the base case that will allow 
for termination:

> 
> Unify (first:TYPE, second: TYPE)
>    will return true on Unification false if not.
> 
> 1. Start
> 2. let t1 = repr first
>    let t2 = repr second

   2.5  if t1 equals t2
	   return true
> 
> 3. match (t1.kind, t2.kind) with
> 
>    case (Integer, Integer) ->
>            return true
> 
>    case (Tvar, _ )  ->
>            t1.link = Some t2
>            return true
> 
>    case (_, Tvar) ->
>            t2.link = Some t1
>            return true
> 
>    case (Record, Record) ->
> 
>            if the record lengths don't match
>               return false
> 
>         t1.link = t2  (***** linked speculatively *****)
> 
>            for each i in 0 to t1.components.size()
>               Unify (t1.components[i], t2.components[i])
>               if Unification fails,
>             t1.link = None
>             unlink all types that were linked until now
>             return false
>           endif
> 
>            for each i in 0 to t1.typeArgs.size()
>               Unify (t1.typeArgs[i], t2.typeArgs[i])
>               if Unification fails,
>             unlink all types that were linked until now
>             return false
>           endif
> 
>        return true
> 
>    case (_, _)  ->
>            return false
> 
> 4. Stop

Swaroop.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-16  8:38       ` Jacques Garrigue
@ 2005-11-16 23:00         ` Swaroop Sridhar
  2005-11-16 23:56           ` Swaroop Sridhar
  0 siblings, 1 reply; 17+ messages in thread
From: Swaroop Sridhar @ 2005-11-16 23:00 UTC (permalink / raw)
  To: Jacques Garrigue, caml-list

Jacques Garrigue wrote:
> There is a problem with your algorithm ... 
> The approach in ocaml is simpler: link at each type node, so that
> already unified types will look equal. 

Let me have another take at the algorithm :

Unify (first:TYPE, second: TYPE)
    will return true on Unification false if not.

1. Start
2. let t1 = repr first
    let t2 = repr second

3. match (t1.kind, t2.kind) with

    case (Integer, Integer) ->
            return true

    case (Tvar, _ )  ->
            t1.link = Some t2
            return true

    case (_, Tvar) ->
            t2.link = Some t1
            return true

    case (Record, Record) ->

            if the record lengths don't match
               return false

  	   t1.link = t2  (***** linked speculatively *****)

            for each i in 0 to t1.components.size()
               Unify (t1.components[i], t2.components[i])
               if Unification fails,
			t1.link = None
			unlink all types that were linked until now
			return false
	      endif

            for each i in 0 to t1.typeArgs.size()
               Unify (t1.typeArgs[i], t2.typeArgs[i])
               if Unification fails,
			unlink all types that were linked until now
			return false
	      endif

        return true

    case (_, _)  ->
            return false

4. Stop

Is this correct/ similar to what Ocaml does?

> Note in this case: the definition of llist is nominal, so this type is
> only iso-recursive, which is much easier to handle.

We might have syntactic restrictions (ex: one of ML's restriction that 
recursion can occur only across variant constructor boundaries, etc) so 
that arbitrary recursion is disallowed. However, from an implementation 
standpoint, I *think* that the above implementation of the unifier is 
easier to do even in the case of iso-recursive types. Is this true?

I thought of introducing explicit fold/unfold operations into the 
algorithm, but it seemed to do more work. If I am wrong, can you please 
suggest modifications to the above algorithm that works (better) only 
for iso-recursive types.

Thanks,
Swaroop.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-16  7:40         ` Keiko Nakata
@ 2005-11-16  8:55           ` Jacques Garrigue
  2005-11-17  1:45             ` Keiko Nakata
  0 siblings, 1 reply; 17+ messages in thread
From: Jacques Garrigue @ 2005-11-16  8:55 UTC (permalink / raw)
  To: keiko; +Cc: Alain.Frisch, caml-list

From: Keiko Nakata <keiko@kurims.kyoto-u.ac.jp>

> I think that it is not easy to know when to apply eta-expansion, 
> namely, to replace a type name with its underlying definition.
> 
> For instance, to check equivalence betweeen the types t and s below:
>  type t = < m : t * t >
>  type 'a tuple = 'a * 'a
>  type s = < m : s tuple >
> 
> the algorithm should memorize that t * t and s tuple are equivalent,
> and then expands s tupl into s * s  
> so as to check between t * t and s * s? 

No need to memorize equivalences: s tuple expands at its head to s * s.
The type checker guarantees that it is always safe to expand the head
of a type (i.e., definitions are well-founded.)
But you're right that abbreviations complicate the unification
algorithm a lot.
In order for unification to succeed above, t must expand to
(< m: 'a * 'a> as 'a), and s too. But to print nicely types we must
keep the abbreviations. This is done by memoizing expansions inside 
the abbreviations themselves. I.e., the expansion of t is actually:
  (< m : t[t='a] * t[t='a] > as 'a)
and that of s is
  (< m : s[s='b] tuple[s='b]> as 'b)
where [t='a] is an internal annotation to the abbreviation. So when
unifying, you can actually check the underlying type of an
abbreviation. But maintaining these abbreviations is rather
involved...
Fo instance abbreviations must be propagated:
  type u = <m : w> and w = u * u
will expand to
  (<m : w[u='a]> as 'a)
so that, if we expand w, we fall back to
  (<m : u[u='a] * u[u='a]>)

Jacques Garrigue


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-16  3:28     ` Swaroop Sridhar
@ 2005-11-16  8:38       ` Jacques Garrigue
  2005-11-16 23:00         ` Swaroop Sridhar
  0 siblings, 1 reply; 17+ messages in thread
From: Jacques Garrigue @ 2005-11-16  8:38 UTC (permalink / raw)
  To: swaroop, swaroop.sridhar; +Cc: caml-list

From: Swaroop Sridhar <swaroop.sridhar@gmail.com>

> Thanks for the clarification. In order to ensure that I understand you 
> correctly, can you please look into the following unification algorithm 
> and see if it is reasonably correct?

There is a problem with your algorithm:
the way you check the unf field is buggy (you dereference both sides),
but this seems a trivial a trivial error.
More importantly, even corrected it will fail when unifying a loop of
length 3 with a loop of length 2:
   t1 = (int * (int * 'a) as 'a)
   t2 = (int * (int * (int * 'b)) as 'b)
when you reach the inner 'b, you have already unrolled t1, so it also
has its unf field set, but not to t2...

The approach in ocaml is simpler: link at each type node, so that
already unified types will look equal. As a result, after unification
you have only a loop of length 1.

> > A few years ago, infinite loops were a commonly reported bug :-)
> 
> I read a couple of postings about this issue. I understand that one can 
> hurt oneself with a type being parameterized itself. I also read that 
> the type system needs to deal with this in order to support objects. 
> Aren't recursive types necessary even to do a simple linked list like:
> 
> type llist = {contents: int; link : mutable llist}

Note in this case: the definition of llist is nominal, so this type is
only iso-recursive, which is much easier to handle.
The difficulties only appears with
  type llist = < contents: int; link : llist >

Jacques Garrigue


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-16  6:47       ` Alain Frisch
@ 2005-11-16  7:40         ` Keiko Nakata
  2005-11-16  8:55           ` Jacques Garrigue
  0 siblings, 1 reply; 17+ messages in thread
From: Keiko Nakata @ 2005-11-16  7:40 UTC (permalink / raw)
  To: Alain.Frisch; +Cc: caml-list

From: Alain Frisch <Alain.Frisch@inria.fr>
> 
> The restriction ensures that structural recursive types are necessarily
> regular. So standard coinductive algorithms (implemented by keeping
> track of visited nodes or by memoization) are ok.

Thanks for the reply.

I think that it is not easy to know when to apply eta-expansion, 
namely, to replace a type name with its underlying definition.

For instance, to check equivalence betweeen the types t and s below:
 type t = < m : t * t >
 type 'a tuple = 'a * 'a
 type s = < m : s tuple >

the algorithm should memorize that t * t and s tuple are equivalent,
and then expands s tupl into s * s  
so as to check between t * t and s * s? 

When type abbreviations are more verobse as in 

 type 'a id = 'a 
 type 'a tuple = 'a id * 'a id 
 type u = < m : < m : u tuple> * < m : u tuple> > 

it seems difficult to know when to memorize in what representations
and when to eta-expand by the definitions.

I know easy standard coinductive algorithms found in textbooks,
but how to handle abbreviations is still unclear for me.

With best regards,
Keiko.




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-16  2:20     ` Keiko Nakata
@ 2005-11-16  6:47       ` Alain Frisch
  2005-11-16  7:40         ` Keiko Nakata
  0 siblings, 1 reply; 17+ messages in thread
From: Alain Frisch @ 2005-11-16  6:47 UTC (permalink / raw)
  To: Keiko Nakata; +Cc: caml-list

Keiko Nakata wrote:
> I am very interested in this subject.
> Since 1) I can define type abbreviations almost artitrary,
> as in  type t = < m : t > ; and 2) type abbreviations can have parameters
> as in type 'a t = < m : 'a > , 
> just keeping a list/set of visited nodes does not seem to be enough,
> especially for structual types.

Structural loops (those that don't cross a datatype) cannot be
arbitrary. The parameters cannot change:

# type 'a t = < m : 'a t >;;
type 'a t = < m : 'a t >
# type 'a t = < m : ('a * 'a) t>;;
In the definition of t, type ('a * 'a) t should be 'a t

The restriction ensures that structural recursive types are necessarily
regular. So standard coinductive algorithms (implemented by keeping
track of visited nodes or by memoization) are ok.

-- Alain


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-15 23:40   ` [Caml-list] " Jacques Garrigue
  2005-11-16  2:20     ` Keiko Nakata
@ 2005-11-16  3:28     ` Swaroop Sridhar
  2005-11-16  8:38       ` Jacques Garrigue
  1 sibling, 1 reply; 17+ messages in thread
From: Swaroop Sridhar @ 2005-11-16  3:28 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

Jacques Garrigue wrote:
> No, types are just implemented as (cyclic) graphs.
> All functions in the type checker have to be careful about not going
> into infinite loops. There are various techniques for that, either
> keeping a list/set of visited nodes, or using some mutable fields.

Thanks for the clarification. In order to ensure that I understand you 
correctly, can you please look into the following unification algorithm 
and see if it is reasonably correct?

Considering a language with integers, records and type variables.
Let record types be unified by structural unification.

My representation of type is (please forgive my sloppy syntax at times):

type KindUnion = Integer | Tvar | Record
type 'a option = None | Some 'a

type TYPE =
  { id: int;
         (* unique ID *)

    kind: kindUnion;
         (* type of this type: integer/ tvar/ record *)

    components: mutable vector of TYPE
         (* vector of types containing legs of a record *)

    typeArgs: mutable vector of TYPE
         (* vector of types containing type-arguments / type-parameters
            of a record *)
         (* example
               type ('a, 'b) rec = { a: 'a->'b; b: int}
                     typeArgs          components
         *)

    link: mutable (TYPE option)
         (* to link unified types *)

    unf: mutable (TYPE option)
         (* This is a marker used by the unifier.
            Initially, this field is set to `None' for all types.
            If we are attempting to unify t1 and t2, the unifier
            will mark t1-> unf = Some t2, and t2-> unf = Some t1
            so that we detect them next time when we recurse *)
}

I also assume that a function repr is defined that will traverse the 
links so that (repr t) will provide the "final" type.

So, now the Unifier algorithm can be written as (in some hypothetical 
algorithmic language):

Unify (first:TYPE, second: TYPE)
    will return true on Unification false if not.

1. Start
2. let t1 = repr first
    let t2 = repr second

3.  (* The unifier will set unf field on the way in and will
        clear it on its way out. So, first test if we have a
        recursive case *)

    if(t1.unf != None and t2.unf != None)
        if(t1.unf == t2.unf)
	  return true
        endif
        if(t2.unf == t1.unf)
           return true
        else
           return false
        endif
    endif


4. (* set the unf fields *)
    if(t1.unf == None and t2.unf != None)
        t1.unf := Some t2
    else
      if(t2.unf == None and t1.unf != None)
        t2.unf := Some t1
      else
        t1.unf = Some t2
        t2.unf = Some t1
      endif
    endif

5. match (t1.kind, t2.kind) with

    case (Integer, Integer) ->
            return true

    case (Tvar, _ )  ->
            t1->link = Some t2
            return true

    case (_, Tvar) ->
            t2->link = Some t1
            return true

    case (Record, Record) ->
            if the record lengths don't match
               return false

            for each i in 0 to t1.components.size()
               Unify (t1.components[i], t2.components[i])
               if Unification fails, return false

            for each i in 0 to t1.typeArgs.size()
               Unify (t1.typeArgs[i], t2.typeArgs[i])
               if Unification fails, return false
	   return true

    case (_, _)  ->
            return false

6. t1.unf = None
    t2.unf= None

7. Stop

Is this algorithm correct? If not, how should it be fixed?

> A few years ago, infinite loops were a commonly reported bug :-)

I read a couple of postings about this issue. I understand that one can 
hurt oneself with a type being parameterized itself. I also read that 
the type system needs to deal with this in order to support objects. 
Aren't recursive types necessary even to do a simple linked list like:

type llist = {contents: int; link : mutable llist}

Thanks again,
Swaroop.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-15 23:40   ` [Caml-list] " Jacques Garrigue
@ 2005-11-16  2:20     ` Keiko Nakata
  2005-11-16  6:47       ` Alain Frisch
  2005-11-16  3:28     ` Swaroop Sridhar
  1 sibling, 1 reply; 17+ messages in thread
From: Keiko Nakata @ 2005-11-16  2:20 UTC (permalink / raw)
  To: caml-list

From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>

> From: Swaroop Sridhar <swaroop@cs.jhu.edu>
> 
> > How are arbitrary recursive types implemented in caml? 
> 
> No, types are just implemented as (cyclic) graphs.
> All functions in the type checker have to be careful about not going
> into infinite loops. There are various techniques for that, either
> keeping a list/set of visited nodes, or using some mutable fields.

I am very interested in this subject.
Since 1) I can define type abbreviations almost artitrary,
as in  type t = < m : t > ; and 2) type abbreviations can have parameters
as in type 'a t = < m : 'a > , 
just keeping a list/set of visited nodes does not seem to be enough,
especially for structual types.
So I think the type checker does some very clever thing.

Regards,
Keiko.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] Recursive types
  2005-11-15 22:44 ` Recursive types Swaroop Sridhar
@ 2005-11-15 23:40   ` Jacques Garrigue
  2005-11-16  2:20     ` Keiko Nakata
  2005-11-16  3:28     ` Swaroop Sridhar
  0 siblings, 2 replies; 17+ messages in thread
From: Jacques Garrigue @ 2005-11-15 23:40 UTC (permalink / raw)
  To: swaroop; +Cc: caml-list

From: Swaroop Sridhar <swaroop@cs.jhu.edu>

> How are arbitrary recursive types implemented in caml? Is it done using 
> an explicit fix point combinator "type" so that the unifier itself does 
> not go into an infinite loop?

No, types are just implemented as (cyclic) graphs.
All functions in the type checker have to be careful about not going
into infinite loops. There are various techniques for that, either
keeping a list/set of visited nodes, or using some mutable fields.
A few years ago, infinite loops were a commonly reported bug :-)

Jacques Garrigue


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] recursive types
  2004-12-13  9:58 ` [Caml-list] " Damien Pous
@ 2004-12-13 12:31   ` skaller
  0 siblings, 0 replies; 17+ messages in thread
From: skaller @ 2004-12-13 12:31 UTC (permalink / raw)
  To: Damien Pous; +Cc: caml-list

On Mon, 2004-12-13 at 20:58, Damien Pous wrote:
> You can do something this:
> 
> type 'a exp_ = [`Num of 'a |`Neg of 'a] 
> 
> class type obj = object 
>   method eql : obj exp_ ->  bool
> end
> 
> type exp = obj exp_

Or the converse (parameterise the class instead).

-- 
John Skaller, mailto:skaller@users.sf.net
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] recursive types
  2004-12-13  9:44 recursive types nakata keiko
@ 2004-12-13  9:58 ` Damien Pous
  2004-12-13 12:31   ` skaller
  0 siblings, 1 reply; 17+ messages in thread
From: Damien Pous @ 2004-12-13  9:58 UTC (permalink / raw)
  To: caml-list

You can do something this:

type 'a exp_ = [`Num of 'a |`Neg of 'a] 

class type obj = object 
  method eql : obj exp_ ->  bool
end

type exp = obj exp_


Damien


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2008-03-24  9:02 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-24  3:16 recursive types Jacques Le Normand
2008-03-24  3:51 ` [Caml-list] " Erik de Castro Lopo
2008-03-24  3:51 ` Erik de Castro Lopo
2008-03-24  8:37 ` Jeremy Yallop
2008-03-24  9:02 ` Remi Vanicat
     [not found] <20050506044107.1698.70519.Mailman@yquem.inria.fr>
2005-11-15 22:44 ` Recursive types Swaroop Sridhar
2005-11-15 23:40   ` [Caml-list] " Jacques Garrigue
2005-11-16  2:20     ` Keiko Nakata
2005-11-16  6:47       ` Alain Frisch
2005-11-16  7:40         ` Keiko Nakata
2005-11-16  8:55           ` Jacques Garrigue
2005-11-17  1:45             ` Keiko Nakata
2005-11-16  3:28     ` Swaroop Sridhar
2005-11-16  8:38       ` Jacques Garrigue
2005-11-16 23:00         ` Swaroop Sridhar
2005-11-16 23:56           ` Swaroop Sridhar
  -- strict thread matches above, loose matches on Subject: below --
2004-12-13  9:44 recursive types nakata keiko
2004-12-13  9:58 ` [Caml-list] " Damien Pous
2004-12-13 12:31   ` skaller

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).