caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* type generalization of recursive calls
@ 2010-02-17 16:34 Stéphane Gimenez
  2010-02-17 19:41 ` [Caml-list] " Boris Yakobowski
  2010-02-18 14:24 ` Stéphane Gimenez
  0 siblings, 2 replies; 7+ messages in thread
From: Stéphane Gimenez @ 2010-02-17 16:34 UTC (permalink / raw)
  To: The Caml Mailing List

Hi,

I just realized that ocaml generalizes the type of a recursively
defined function *only* for calls which are outside it's own
definition. Recursive calls cannot use a generalized type.

In fact, I'm tring to work with such a data type:

type 'a t =
  | E
  | D of 'a t * 'a t
  | O of 'a
  | I of 'a t t

And, I'm forced to use some dark magic to define simple operations on
it:

let rec map (f : 'a -> 'b) : 'a t -> 'b t =
  begin function
  | E -> E
  | D (t1, t2) -> D (map f t1, map f t2)
  | O a -> O (f a)
  | I tt ->
      I ((Obj.magic map : ('a t -> 'b t) -> 'a t t -> 'b t t) (map f) tt)
  end

Questions:
  - Is it theoreticaly safe to generalize recursive calls ?
  - Is there a syntactical trick to use generalized recursive calls ?
  - Could such a generalization be added to the type checker ?
      - Performance issues ?
      - More obfusctated type checking errors ?

In a related disscution I found, one asked about generalization
between mutualy recursive definitions (same problem). No answers, but
maybe I just lack pointers.

Cheers,
Stéphane


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

* Re: [Caml-list] type generalization of recursive calls
  2010-02-17 16:34 type generalization of recursive calls Stéphane Gimenez
@ 2010-02-17 19:41 ` Boris Yakobowski
  2010-02-17 20:25   ` Dario Teixeira
  2010-02-18 14:24 ` Stéphane Gimenez
  1 sibling, 1 reply; 7+ messages in thread
From: Boris Yakobowski @ 2010-02-17 19:41 UTC (permalink / raw)
  To: Stéphane Gimenez, The Caml Mailing List

Hi Gim,

On Wed, Feb 17, 2010 at 5:34 PM, Stéphane Gimenez
<stephane.gimenez@pps.jussieu.fr> wrote:
> Questions:
>  - Is it theoreticaly safe to generalize recursive calls ?

Yes. And this is done in explicitly-typed languages, such as in Coq.

>  - Is there a syntactical trick to use generalized recursive calls ?

Not in the current Ocaml, as type annotations cannot be used to
introduce type polymorphism. However, see below.

>  - Could such a generalization be added to the type checker ?
>      - Performance issues ?
>      - More obfusctated type checking errors ?

Unfotunately, it is worse than that : type inference is undecidable in
the presence of polymorphic recursion. See e.g.
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.3091

> In a related disscution I found, one asked about generalization
> between mutualy recursive definitions (same problem). No answers, but
> maybe I just lack pointers.

If I'm not mistaken, you can encode all cases of polymorphic recursion
using mutual monomorphic recursion. For your example, this would give

let rec map f = function
  | E -> E
  | D (t1, t2) -> D (map f t1, map f t2)
  | O a -> O (f a)
  | I tt -> I (map2 (map f) tt)
and map2 x = map x

Here, map is always called with type ('a -> 'b) -> 'a t -> 'b t inside
its own body (and is instantiated only inside map2). Thus this second
problem is even harder than polymorphic recursion.

Finally, starting from Ocaml 3.13, you can simply write

let rec map : 'a 'b. ('a -> 'b) -> 'a t -> 'b t = fun f -> function
  | E -> E
  | D (t1, t2) -> D (map f t1, map f t2)
  | O a -> O (f a)
  | I tt -> I (map (map f) tt)

Hope this helps,

-- 
Boris


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

* Re: [Caml-list] type generalization of recursive calls
  2010-02-17 19:41 ` [Caml-list] " Boris Yakobowski
@ 2010-02-17 20:25   ` Dario Teixeira
  2010-02-17 20:33     ` Boris Yakobowski
  0 siblings, 1 reply; 7+ messages in thread
From: Dario Teixeira @ 2010-02-17 20:25 UTC (permalink / raw)
  To: Stéphane Gimenez, The Caml Mailing List, boris

Hi,

> Finally, starting from Ocaml 3.13, you can simply write
> 
> let rec map : 'a 'b. ('a -> 'b) -> 'a t -> 'b t =
> fun f -> function
>   | E -> E
>   | D (t1, t2) -> D (map f t1, map f t2)
>   | O a -> O (f a)
>   | I tt -> I (map (map f) tt)

Assuming "3.13" is not a typo, and that you do not actually mean the
upcoming 3.12, what features can we expect in future versions of Ocaml?

Just curious,
Dario Teixeira






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

* Re: [Caml-list] type generalization of recursive calls
  2010-02-17 20:25   ` Dario Teixeira
@ 2010-02-17 20:33     ` Boris Yakobowski
  0 siblings, 0 replies; 7+ messages in thread
From: Boris Yakobowski @ 2010-02-17 20:33 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: The Caml Mailing List

On Wed, Feb 17, 2010 at 9:25 PM, Dario Teixeira <darioteixeira@yahoo.com> wrote:
> Assuming "3.13" is not a typo, and that you do not actually mean the
> upcoming 3.12, what features can we expect in future versions of Ocaml?

Sorry, I went too far. I indeed meant 3.12.

-- 
Boris


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

* Re: type generalization of recursive calls
  2010-02-17 16:34 type generalization of recursive calls Stéphane Gimenez
  2010-02-17 19:41 ` [Caml-list] " Boris Yakobowski
@ 2010-02-18 14:24 ` Stéphane Gimenez
  1 sibling, 0 replies; 7+ messages in thread
From: Stéphane Gimenez @ 2010-02-18 14:24 UTC (permalink / raw)
  To: The Caml Mailing List

Hi,

Thanks for your answers. Thanks to Damien for the handy
workarounds and to Boris for the sevral insightful comments.

I'll probably switch to the svn version, waiting for 3.12...

I think 3.13 was a typo, see:
  http://caml.inria.fr/svn/ocaml/trunk/Changes

Stéphane

PS:
btw, looks like coq is not really fond of this data type:

Inductive t a : Type :=
  | E : t a
  | D : t a -> t a -> t a
  | O : a -> t a
  | I : t (t a) -> t a
.

Error: Non strictly positive occurrence of "t" in "t (t a) -> t a".


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

* Re: [Caml-list] type generalization of recursive calls
@ 2010-02-17 18:13 Damien Guichard
  0 siblings, 0 replies; 7+ messages in thread
From: Damien Guichard @ 2010-02-17 18:13 UTC (permalink / raw)
  To: Stéphane Gimenez; +Cc: The Caml Mailing List

I have to apologize because your definition is actually correct.
Sorry i have read it too fast and didn't see map burried in type casting.

It seems to me your are doing structural recursion on some binary tree structure.
Presumably to fast-merge binary heaps or something like that.
pa_polyrec is probably a must have for such things.

- damien



Le 17/02/2010 à 17:34:24, "Stéphane Gimenez" <stephane.gimenez@pps.jussieu.fr>
à écrit :
>
>Hi,
>
>I just realized that ocaml generalizes the type of a recursively
>defined function *only* for calls which are outside it's own
>definition. Recursive calls cannot use a generalized type.
>
>In fact, I'm tring to work with such a data type:
>
>type 'a t =
>  | E
>  | D of 'a t * 'a t
>  | O of 'a
>  | I of 'a t t
>
>And, I'm forced to use some dark magic to define simple operations on
>it:
>
>let rec map (f : 'a -> 'b) : 'a t -> 'b t =
>  begin function
>  | E -> E
>  | D (t1, t2) -> D (map f t1, map f t2)
>  | O a -> O (f a)
>  | I tt ->
>      I ((Obj.magic map : ('a t -> 'b t) -> 'a t t -> 'b t t) (map f) tt)
>  end
>
>Questions:
>  - Is it theoreticaly safe to generalize recursive calls ?
>  - Is there a syntactical trick to use generalized recursive calls ?
>  - Could such a generalization be added to the type checker ?
>      - Performance issues ?
>      - More obfusctated type checking errors ?
>
>In a related disscution I found, one asked about generalization
>between mutualy recursive definitions (same problem). No answers, but
>maybe I just lack pointers.
>
>Cheers,
>Stéphane
>
>_______________________________________________
>Caml-list mailing list. Subscription management:
>http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
>Archives: http://caml.inria.fr
>Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>Bug reports: http://caml.inria.fr/bin/caml-bugs
>


--
Mail created using EssentialPIM Free - www.essentialpim.com




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

* Re: [Caml-list] type generalization of recursive calls
@ 2010-02-17 17:59 Damien Guichard
  0 siblings, 0 replies; 7+ messages in thread
From: Damien Guichard @ 2010-02-17 17:59 UTC (permalink / raw)
  To: Stéphane Gimenez; +Cc: The Caml Mailing List

Hello,

First, you really need strong tyupe checking because your definition is actually
incorrect.

Second, see polymorphic-recursion :
http://alaska-kamtchatka.blogspot.com/2009/05/polymorphic-recursion.html

Be sure to read the comments by bluestorm.

There is also pa_polyrec, a syntax extension for polymorphic recursion in OCaml
:
http://www.mail-archive.com/caml-list@yquem.inria.fr/msg04795.html


Finally, here is your (corrected) code using vanilla ocaml : 

type map =
  { map : 'a 'b. ('a -> 'b) -> 'a t -> 'b t }
let map =
  let rec map =
    { map = fun f -> function
    | E -> E
    | D (t1, t2) -> D (map.map f t1, map.map f t2)
    | O a -> O (f a)
    | I tt -> I (map.map (map.map f) tt) 
    }
  in map.map   


- damien



Le 17/02/2010 à 17:34:24, "Stéphane Gimenez" <stephane.gimenez@pps.jussieu.fr>
à écrit :
>
>Hi,
>
>I just realized that ocaml generalizes the type of a recursively
>defined function *only* for calls which are outside it's own
>definition. Recursive calls cannot use a generalized type.
>
>In fact, I'm tring to work with such a data type:
>
>type 'a t =
>  | E
>  | D of 'a t * 'a t
>  | O of 'a
>  | I of 'a t t
>
>And, I'm forced to use some dark magic to define simple operations on
>it:
>
>let rec map (f : 'a -> 'b) : 'a t -> 'b t =
>  begin function
>  | E -> E
>  | D (t1, t2) -> D (map f t1, map f t2)
>  | O a -> O (f a)
>  | I tt ->
>      I ((Obj.magic map : ('a t -> 'b t) -> 'a t t -> 'b t t) (map f) tt)
>  end
>
>Questions:
>  - Is it theoreticaly safe to generalize recursive calls ?
>  - Is there a syntactical trick to use generalized recursive calls ?
>  - Could such a generalization be added to the type checker ?
>      - Performance issues ?
>      - More obfusctated type checking errors ?
>
>In a related disscution I found, one asked about generalization
>between mutualy recursive definitions (same problem). No answers, but
>maybe I just lack pointers.
>
>Cheers,
>Stéphane
>
>_______________________________________________
>Caml-list mailing list. Subscription management:
>http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
>Archives: http://caml.inria.fr
>Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>Bug reports: http://caml.inria.fr/bin/caml-bugs
>


--
Mail created using EssentialPIM Free - www.essentialpim.com




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

end of thread, other threads:[~2010-02-18 14:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-17 16:34 type generalization of recursive calls Stéphane Gimenez
2010-02-17 19:41 ` [Caml-list] " Boris Yakobowski
2010-02-17 20:25   ` Dario Teixeira
2010-02-17 20:33     ` Boris Yakobowski
2010-02-18 14:24 ` Stéphane Gimenez
2010-02-17 17:59 [Caml-list] " Damien Guichard
2010-02-17 18:13 Damien Guichard

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