caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Smells like duck-typing
@ 2007-10-17 13:35 Dario Teixeira
  2007-10-17 14:13 ` [Caml-list] " Arnaud Spiwack
                   ` (7 more replies)
  0 siblings, 8 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-17 13:35 UTC (permalink / raw)
  To: caml-list

Hi,

I have been trying to reach a sane modelling in OCaml for a "story"
data structure in a CMS.  The problem is that I find myself needing
a degree of expressiveness that I can't find in the language!  I do
have a working, tentative solution, but it has a few ugly aspects
that I would very much like to improve.  Details follow.  (Sorry
for the long post; at least I hope it's not too dense and hard to
follow).

A "full" story record is defined like this:

type full_t =
	{
	id: int;
	title: string;
	intro: string;
	body: string;
	}

(in reality there are other fields, but I'll ommit them for the sake
of clarity).  In addition, stories can also come in "blurb" and "fresh"
types, which are essentially (non-disjoint) subsets of the type above:

type blurb_t =				type fresh_t =
	{					{
	id: int;				title: string;
	title: string;				intro: string;
	intro: string;				body: string;
	}					}


At last, I have a function "print_metadata" that takes as parameter
either a "full" or a "blurb" story, printing its id and title:

let print_metadata s =
	Printf.printf "%d: %s\n" s.id s.title

Now, I have been looking for the best way to model this situation
in OCaml.  Here are some options:

a) Use record types, as shown above.  However, to avoid namespace clashes,
   this would entail putting each record in its own module (neat) or at
   least salting each field name (ugly).  Suppose that I opt for the former
   option and create the modules Full, Blurb, and Fresh, each with a type t:

   type story_t = [`Full of Full.t | `Blurb of Blurb.t | `Fresh of Fresh.t]

   Note that I have chosen a polymorphic variant because print_metadata only
   makes sense for Full.t and Blurb.t types.  However, this solution means
   there can't be any code sharing between the two branchings, which is just
   ridiculous considering they are essentially identical:  (and in the real
   world, print_metadata is a much bigger function).

   let print_metadata = function
	| `Full s  -> Printf.printf "%d: %s\n" s.Full.id s.Full.title
	| `Blurb s -> Printf.printf "%d: %s\n" s.Blurb.id s.Blurb.title

b) Use only full_t and make all fields option types.  However, not only is
   this cumbersome to use, but is also conceptually wrong, because it does
   not capture the fact that, for example, all "blurb" stories have three
   *mandatory* fields.

c) Actually put the "Objective" part of OCaml to use.  This is the solution
   I am using at the moment.  This is what it looks like:

   class story (id, title, intro, body) =
   object
   	val id: int option = id
   	val title: string option = title
   	val intro: string option = intro
   	val body: string option = body
   
   	method id =
   		match id with
   		| Some thing -> thing
   		| None -> failwith "oops"
   
   	method title =
   		match title with
   		| Some thing -> thing
   		| None -> failwith "oops"
   
   	method intro =
   		match intro with
   		| Some thing -> thing
   		| None -> failwith "oops"
   
   	method body =
   		match body with
   		| Some thing -> thing
   		| None -> failwith "oops"
   end

   
   class full (id, title, intro, body) =
   object
   	inherit story (Some id, Some title, Some intro, Some body)
   end
   
   class blurb (id, title, intro) =
   object
   	inherit story (Some id, Some title, Some intro, None)
   end
   
   class fresh (title, intro, body) =
   object
   	inherit story (None, Some title, Some intro, Some body)
   end

   
   let print_metadata s =
   	Printf.printf "%d: %s\n" s#id s#title
  

This last solution has two big advantages: it provides a relatively
clean interface to users of the module, and allows for code reuse
without duplication.  Thanks to the way the object system in OCaml
works, the print_metadata function can operate on any objects that
have the #id and #title methods.  It feels almost like the duck-typing
present in languages such as Python (though different, of course).

However, I'm still not completely happy with it, mostly because the
hackery with the optional types inside the story class is ugly.  Does
someone have any clever ideas on how this could be modelled/improved?

Thanks,
Dario





      ___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
http://uk.answers.yahoo.com/ 


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
@ 2007-10-17 14:13 ` Arnaud Spiwack
  2007-10-17 14:47   ` Dario Teixeira
  2007-10-17 14:25 ` Daniel Bünzli
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 55+ messages in thread
From: Arnaud Spiwack @ 2007-10-17 14:13 UTC (permalink / raw)
  Cc: caml-list

Hi,

I think your solution is to fully use the "Objective" part of OCaml, 
that is, using subtyping (technically it's polymorphic rows typing) :

class full_t (id, title, intro, body) =
   object
        method id : int = id
        method title : string = title
        method intro : string = intro
        method body : string= body
    end

class blurb_t (id, title, intro) =
   object
        method id : int = id
        method title : string = title
        method intro : string = intro
    end


# let print_metadata s = Printf.printf "%d: %s\n" s#id s#title
val print_metadata : < id : int; title : string; .. > -> unit = <fun>

# print_metadata (new full_t (1, "title", "intro", "body"));;
1: title

# print_metadata (new blurb_t (1, "title", "intro"));;
1: title

Dario Teixeira a écrit :
> Hi,
>
> I have been trying to reach a sane modelling in OCaml for a "story"
> data structure in a CMS.  The problem is that I find myself needing
> a degree of expressiveness that I can't find in the language!  I do
> have a working, tentative solution, but it has a few ugly aspects
> that I would very much like to improve.  Details follow.  (Sorry
> for the long post; at least I hope it's not too dense and hard to
> follow).
>
> A "full" story record is defined like this:
>
> type full_t =
> 	{
> 	id: int;
> 	title: string;
> 	intro: string;
> 	body: string;
> 	}
>
> (in reality there are other fields, but I'll ommit them for the sake
> of clarity).  In addition, stories can also come in "blurb" and "fresh"
> types, which are essentially (non-disjoint) subsets of the type above:
>
> type blurb_t =				type fresh_t =
> 	{					{
> 	id: int;				title: string;
> 	title: string;				intro: string;
> 	intro: string;				body: string;
> 	}					}
>
>
> At last, I have a function "print_metadata" that takes as parameter
> either a "full" or a "blurb" story, printing its id and title:
>
> let print_metadata s =
> 	Printf.printf "%d: %s\n" s.id s.title
>
> Now, I have been looking for the best way to model this situation
> in OCaml.  Here are some options:
>
> a) Use record types, as shown above.  However, to avoid namespace clashes,
>    this would entail putting each record in its own module (neat) or at
>    least salting each field name (ugly).  Suppose that I opt for the former
>    option and create the modules Full, Blurb, and Fresh, each with a type t:
>
>    type story_t = [`Full of Full.t | `Blurb of Blurb.t | `Fresh of Fresh.t]
>
>    Note that I have chosen a polymorphic variant because print_metadata only
>    makes sense for Full.t and Blurb.t types.  However, this solution means
>    there can't be any code sharing between the two branchings, which is just
>    ridiculous considering they are essentially identical:  (and in the real
>    world, print_metadata is a much bigger function).
>
>    let print_metadata = function
> 	| `Full s  -> Printf.printf "%d: %s\n" s.Full.id s.Full.title
> 	| `Blurb s -> Printf.printf "%d: %s\n" s.Blurb.id s.Blurb.title
>
> b) Use only full_t and make all fields option types.  However, not only is
>    this cumbersome to use, but is also conceptually wrong, because it does
>    not capture the fact that, for example, all "blurb" stories have three
>    *mandatory* fields.
>
> c) Actually put the "Objective" part of OCaml to use.  This is the solution
>    I am using at the moment.  This is what it looks like:
>
>    class story (id, title, intro, body) =
>    object
>    	val id: int option = id
>    	val title: string option = title
>    	val intro: string option = intro
>    	val body: string option = body
>    
>    	method id =
>    		match id with
>    		| Some thing -> thing
>    		| None -> failwith "oops"
>    
>    	method title =
>    		match title with
>    		| Some thing -> thing
>    		| None -> failwith "oops"
>    
>    	method intro =
>    		match intro with
>    		| Some thing -> thing
>    		| None -> failwith "oops"
>    
>    	method body =
>    		match body with
>    		| Some thing -> thing
>    		| None -> failwith "oops"
>    end
>
>    
>    class full (id, title, intro, body) =
>    object
>    	inherit story (Some id, Some title, Some intro, Some body)
>    end
>    
>    class blurb (id, title, intro) =
>    object
>    	inherit story (Some id, Some title, Some intro, None)
>    end
>    
>    class fresh (title, intro, body) =
>    object
>    	inherit story (None, Some title, Some intro, Some body)
>    end
>
>    
>    let print_metadata s =
>    	Printf.printf "%d: %s\n" s#id s#title
>   
>
> This last solution has two big advantages: it provides a relatively
> clean interface to users of the module, and allows for code reuse
> without duplication.  Thanks to the way the object system in OCaml
> works, the print_metadata function can operate on any objects that
> have the #id and #title methods.  It feels almost like the duck-typing
> present in languages such as Python (though different, of course).
>
> However, I'm still not completely happy with it, mostly because the
> hackery with the optional types inside the story class is ugly.  Does
> someone have any clever ideas on how this could be modelled/improved?
>
> Thanks,
> Dario
>
>
>
>
>
>       ___________________________________________________________
> Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
> now.
> http://uk.answers.yahoo.com/ 
>
> _______________________________________________
> 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
>
>   


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
  2007-10-17 14:13 ` [Caml-list] " Arnaud Spiwack
@ 2007-10-17 14:25 ` Daniel Bünzli
  2007-10-17 15:03   ` skaller
  2007-10-17 14:33 ` Chris King
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 55+ messages in thread
From: Daniel Bünzli @ 2007-10-17 14:25 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list

Use a record with a phantom type (the type must be abstract for this  
to work). The record has the common properties as fields and a data  
field which is either a list of tagged values (if many kinds of  
stories share the same fields) or a variant for the data specific to  
a kind of story. If there are operations that are allowed only on  
some kind of stories constrain the phantom type in the signature to  
enforce this statically.

Best,

Daniel

module Story : sig

  type 'a t constraint 'a = [< `Full | `Blurb | `Fresh ]

(* Story creators *)
  val full : ... -> `Full t
  val blurb : ... -> `Blurb t
  val fresh : ... -> `Fresh t

  val print_meta_data : [< `Full | `Blurb ] t -> unit

end = struct

   type 'a t = {
       id : int;
       title : string;
       intro : string;
       data : ...
    }
   ...
end


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
  2007-10-17 14:13 ` [Caml-list] " Arnaud Spiwack
  2007-10-17 14:25 ` Daniel Bünzli
@ 2007-10-17 14:33 ` Chris King
  2007-10-17 14:59   ` Dario Teixeira
  2007-10-17 15:24 ` Vincent Aravantinos
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 55+ messages in thread
From: Chris King @ 2007-10-17 14:33 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list

On 10/17/07, Dario Teixeira <darioteixeira@yahoo.com> wrote:
> c) Actually put the "Objective" part of OCaml to use.  This is the solution
>    I am using at the moment.  This is what it looks like:
>
>    class story (id, title, intro, body) =
>    object
>         val id: int option = id
>         val title: string option = title
>         val intro: string option = intro
>         val body: string option = body
>
>         method id =
>                 match id with
>                 | Some thing -> thing
>                 | None -> failwith "oops"
>
>         method title =
>                 match title with
>                 | Some thing -> thing
>                 | None -> failwith "oops"
>
>         method intro =
>                 match intro with
>                 | Some thing -> thing
>                 | None -> failwith "oops"
>
>         method body =
>                 match body with
>                 | Some thing -> thing
>                 | None -> failwith "oops"
>    end
>
>
>    class full (id, title, intro, body) =
>    object
>         inherit story (Some id, Some title, Some intro, Some body)
>    end
>
>    class blurb (id, title, intro) =
>    object
>         inherit story (Some id, Some title, Some intro, None)
>    end
>
>    class fresh (title, intro, body) =
>    object
>         inherit story (None, Some title, Some intro, Some body)
>    end
>
>
>    let print_metadata s =
>         Printf.printf "%d: %s\n" s#id s#title

Why not have different object types for each of the story types? e.g.

type full = < id: int; title: string; intro: string; body: string >
type blurb = < id: int; title: string; intro: string >
type fresh = < title: string; intro: string; body: string >

print_metadata can remain as is in your object example.  In order to
allow functions that operate differently depending on which story type
they're given, use a polymorphic variant like in your first example.
If you wanted print_metadata to take such a type, it could be written
as:

let print_metadata s =
  let s' =
    match s with
    | `Full f -> (f :> < id: int; title: string >)
    | `Blurb f -> (f :> < id: int; title: string >)
  in
  Printf.printf "%d: %s\n" s'#id s'#title

(Note the match gook is unfortunately needed to get the typing right...)

If on the other hand you wanted to ditch objects entirely, you could
do a similar thing using modules and functors.  E.g.:

module Full = struct
  type t = { id: int; title: string; intro: string; body: string }
  let id s = s.id
  let title s = s.title
  let intro s = s.intro
  let body s = s.body
end

(* etc. *)

module Print_metadata(S: sig type t val id: t -> string val title: t
-> string) = struct
  let f s = Printf.printf "%d: %s\n" (S.id s) (S.title s)
end

Of course, since calls to print_metadata now look like
"Print_metadata(Full).f story", you're essentially forced to write out
the types of everything, which is probably what you wanted to avoid
anyway.

HTH,
Chris


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 14:13 ` [Caml-list] " Arnaud Spiwack
@ 2007-10-17 14:47   ` Dario Teixeira
  0 siblings, 0 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-17 14:47 UTC (permalink / raw)
  To: caml-list

> I think your solution is to fully use the "Objective" part of OCaml, 
> that is, using subtyping (technically it's polymorphic rows typing) :

Hi,

Yes, you're right.  Doing away with the inheritance -- while having the
disadvantage of forcing the redeclaration of all common fields -- does
allow me to throw away the ugliness of the option types.  It is in the
end the lesser of two evils...

Cheers,
Dario



      ___________________________________________________________ 
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 14:33 ` Chris King
@ 2007-10-17 14:59   ` Dario Teixeira
  0 siblings, 0 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-17 14:59 UTC (permalink / raw)
  To: Chris King; +Cc: caml-list

Hi,

> Why not have different object types for each of the story types? e.g.

Yes, other people have suggested the same, and while not a perfect
solution (because of the reduplication of fields), the object subtyping
feature of OCaml (the bit that smells a lot like duck-typing...)
is powerful enough to avoid the code duplication in functions such
as print_metadata.  More important, it avoids the ugly hackery with
option types.


> If on the other hand you wanted to ditch objects entirely, you could
> do a similar thing using modules and functors.  E.g.:

That is actually an interesting approach.  If I'm not mistaken, the
semantics for the parameter to a functor is "a module whose signature
contains at least this", which is again similar to duck-typing...

Cheers,
Dario





      ___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
http://uk.answers.yahoo.com/


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 14:25 ` Daniel Bünzli
@ 2007-10-17 15:03   ` skaller
  2007-10-17 15:13     ` Dario Teixeira
  0 siblings, 1 reply; 55+ messages in thread
From: skaller @ 2007-10-17 15:03 UTC (permalink / raw)
  To: Daniel Bünzli; +Cc: Dario Teixeira, caml-list


On Wed, 2007-10-17 at 16:25 +0200, Daniel Bünzli wrote:
> Use a record with a phantom type (the type must be abstract for this  
> to work).

I would use something weaker, and I wouldn't use objects
either. To me, this is essentially a dynamic scenario,
so the data type should be dynamic. For example:

	type field_t = [
	| `Title of string
	| `Intro of string
	| `Body of string
	| `Field of string * string
	]

	type story_t = field_t list


		

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 15:03   ` skaller
@ 2007-10-17 15:13     ` Dario Teixeira
  2007-10-17 15:25       ` Arnaud Spiwack
                         ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-17 15:13 UTC (permalink / raw)
  To: skaller, Daniel Bünzli; +Cc: caml-list

> I would use something weaker, and I wouldn't use objects
> either. To me, this is essentially a dynamic scenario,
> so the data type should be dynamic. For example:
> 
> 	type field_t = [
> 	| `Title of string
> 	| `Intro of string
> 	| `Body of string
> 	| `Field of string * string
> 	]
> 
> 	type story_t = field_t list
> 

Hi,

Interesting idea, but how would you access the fields in a convenient
manner?  Note that nothing beats record access (say, story.title) or even
object method call (story#title) in convenience and readability.

(I guess the convenience aspect could be sorted out with a syntax
extension, but then we're moving into far more complex territory
than I hope is necessary...)

Cheers,
Dario




      ___________________________________________________________ 
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
                   ` (2 preceding siblings ...)
  2007-10-17 14:33 ` Chris King
@ 2007-10-17 15:24 ` Vincent Aravantinos
  2007-10-17 15:26 ` Zheng Li
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 55+ messages in thread
From: Vincent Aravantinos @ 2007-10-17 15:24 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list


Le 17 oct. 07 à 15:35, Dario Teixeira a écrit :

> I have been trying to reach a sane modelling in OCaml for a "story"
> data structure in a CMS.
(...)
> Does someone have any clever ideas on how this could be
> modelled/improved?

Also take a look at:

http://tech.groups.yahoo.com/group/ocaml_beginners/message/8654

Cheers,
V.

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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 15:13     ` Dario Teixeira
@ 2007-10-17 15:25       ` Arnaud Spiwack
  2007-10-17 15:32       ` Daniel Bünzli
  2007-10-17 16:52       ` skaller
  2 siblings, 0 replies; 55+ messages in thread
From: Arnaud Spiwack @ 2007-10-17 15:25 UTC (permalink / raw)
  To: caml-list

First, let us emphasize that this goes down to the original "option" 
thing, but in a more dynamic fashion. It is very possible to wrap it 
back with phantom types, which would probably be a good idea in this case.

My taste for this sort of thing is to make all this a finite map of some 
sort (might be implemented as a list, but the primitive should ensure a 
form of unicity, therefore an additional layer of abstract datatype).

Then you would need a type to query over :
"field_field = [ `Title | `Intro | `Body | `Field ].

Implement a function "fetch" that returns you a field_t or raises an 
exception (you can do similarily a function "mem" etc).

Then you can define

let title m = let `Title s = fetch `Title m in s;;
and give it type [> `Title ] story -> string   (to be sure not to raise 
an exception, modulo right phantom type invariants).

That's my own methodology for this sort of types.



Arnaud Spiwack


Dario Teixeira a écrit :
>> I would use something weaker, and I wouldn't use objects
>> either. To me, this is essentially a dynamic scenario,
>> so the data type should be dynamic. For example:
>>
>> 	type field_t = [
>> 	| `Title of string
>> 	| `Intro of string
>> 	| `Body of string
>> 	| `Field of string * string
>> 	]
>>
>> 	type story_t = field_t list
>>
>>     
>
> Hi,
>
> Interesting idea, but how would you access the fields in a convenient
> manner?  Note that nothing beats record access (say, story.title) or even
> object method call (story#title) in convenience and readability.
>
> (I guess the convenience aspect could be sorted out with a syntax
> extension, but then we're moving into far more complex territory
> than I hope is necessary...)
>
> Cheers,
> Dario
>
>
>
>
>       ___________________________________________________________ 
> Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html
>
> _______________________________________________
> 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
>
>   


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

* Re: Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
                   ` (3 preceding siblings ...)
  2007-10-17 15:24 ` Vincent Aravantinos
@ 2007-10-17 15:26 ` Zheng Li
  2007-10-18 16:13   ` Zheng Li
  2007-10-17 19:59 ` [Caml-list] " Richard Jones
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 55+ messages in thread
From: Zheng Li @ 2007-10-17 15:26 UTC (permalink / raw)
  To: caml-list


Hi,

I would vote for the object solution. However, both record and object have
their own pros and cons. The actual solution should depends on your requirement
and taste. Just for an example, the following data structure is a possibility:

# type +'a t = {title:string; intro:string; extra:'a} constraint 'a = < .. >;;
# let fresh (title,intro,(body:string)) = 
  {title=title; intro=intro; extra=object method body=body end};;
# let blurb ((id:int),title,intro) =
  {title=title; intro=intro; extra=object method id=id end};;
# let print_metadata s = Printf.printf "%d: %s\n" s.extra#id s.title;;
val print_metadata : < id : int; .. > t -> unit = <fun>

Dario Teixeira <darioteixeira@yahoo.com> writes:
> I have been trying to reach a sane modelling in OCaml for a "story"
> data structure in a CMS.  The problem is that I find myself needing
> a degree of expressiveness that I can't find in the language!  I do
> have a working, tentative solution, but it has a few ugly aspects
> that I would very much like to improve.  Details follow.  (Sorry
> for the long post; at least I hope it's not too dense and hard to
> follow).

-- 
Zheng Li
http://www.pps.jussieu.fr/~li


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 15:13     ` Dario Teixeira
  2007-10-17 15:25       ` Arnaud Spiwack
@ 2007-10-17 15:32       ` Daniel Bünzli
  2007-10-17 16:21         ` Chris King
  2007-10-17 16:57         ` [Caml-list] Smells like duck-typing skaller
  2007-10-17 16:52       ` skaller
  2 siblings, 2 replies; 55+ messages in thread
From: Daniel Bünzli @ 2007-10-17 15:32 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: skaller, caml-list


Le 17 oct. 07 à 17:13, Dario Teixeira a écrit :

>> 	type field_t = [
>> 	| `Title of string
>> 	| `Intro of string
>> 	| `Body of string
>> 	| `Field of string * string
>> 	]
>>
>> 	type story_t = field_t list
>>
> Interesting idea,

If this is right for you then what you want is property lists and  
these two solutions [1,2] may be of interest to you.

Daniel

[1] http://mlton.org/PropertyList
[2] http://caml.inria.fr/pub/ml-archives/caml-list/ 
2005/07/1b7a28921aa0a0e002df9e67ace7b60e.fr.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 15:32       ` Daniel Bünzli
@ 2007-10-17 16:21         ` Chris King
  2007-10-18  7:28           ` Stefano Zacchiroli
  2007-10-17 16:57         ` [Caml-list] Smells like duck-typing skaller
  1 sibling, 1 reply; 55+ messages in thread
From: Chris King @ 2007-10-17 16:21 UTC (permalink / raw)
  To: Daniel Bünzli; +Cc: Dario Teixeira, caml-list, skaller

On 10/17/07, Daniel Bünzli <daniel.buenzli@epfl.ch> wrote:
> [2] http://caml.inria.fr/pub/ml-archives/caml-list/2005/07/1b7a28921aa0a0e002df9e67ace7b60e.fr.html

See also Jacques' follow up, where he provides a syntax extension for
these "polymorphic maps" (essentially type-safe property lists):
http://caml.inria.fr/pub/ml-archives/caml-list/2005/07/314a9eb55585d32e7876ef424f5994ae.fr.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 15:13     ` Dario Teixeira
  2007-10-17 15:25       ` Arnaud Spiwack
  2007-10-17 15:32       ` Daniel Bünzli
@ 2007-10-17 16:52       ` skaller
  2007-10-17 16:59         ` Robert Fischer
  2 siblings, 1 reply; 55+ messages in thread
From: skaller @ 2007-10-17 16:52 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: Daniel Bünzli, caml-list


On Wed, 2007-10-17 at 16:13 +0100, Dario Teixeira wrote:
> > I would use something weaker, and I wouldn't use objects
> > either. To me, this is essentially a dynamic scenario,
> > so the data type should be dynamic. For example:
> > 
> > 	type field_t = [
> > 	| `Title of string
> > 	| `Intro of string
> > 	| `Body of string
> > 	| `Field of string * string
> > 	]
> > 
> > 	type story_t = field_t list
> > 
> 
> Hi,
> 
> Interesting idea, but how would you access the fields in a convenient
> manner?  

let rec get_title ls = match ls with
| `Title s :: _ -> s
| _ ::t -> get_title t
| [] -> raise Not_found (* sucks.. *)


-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 15:32       ` Daniel Bünzli
  2007-10-17 16:21         ` Chris King
@ 2007-10-17 16:57         ` skaller
  1 sibling, 0 replies; 55+ messages in thread
From: skaller @ 2007-10-17 16:57 UTC (permalink / raw)
  To: Daniel Bünzli; +Cc: Dario Teixeira, caml-list


On Wed, 2007-10-17 at 17:32 +0200, Daniel Bünzli wrote:
> Le 17 oct. 07 à 17:13, Dario Teixeira a écrit :
> 
> >> 	type field_t = [
> >> 	| `Title of string
> >> 	| `Intro of string
> >> 	| `Body of string
> >> 	| `Field of string * string
> >> 	]
> >>
> >> 	type story_t = field_t list
> >>
> > Interesting idea,
> 
> If this is right for you then what you want is property lists and  
> these two solutions [1,2] may be of interest to you.

Yes, my 'solution' is just a hint. Felix actually uses
something similar to the above structure to record properties 
of functions, eg 'pure', 'inline', etc.

This kind of data structure is weakly typed, but that's 
part of the idea. Someone probably has an actual representation
of BibTeX data, which is similar in spirit.

Perhaps this weak typing is too weak and can be beefed up,
for example if the title is mandatory, a record PLUS
a property list.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 16:52       ` skaller
@ 2007-10-17 16:59         ` Robert Fischer
  0 siblings, 0 replies; 55+ messages in thread
From: Robert Fischer @ 2007-10-17 16:59 UTC (permalink / raw)
  To: skaller; +Cc: Dario Teixeira, caml-list, Daniel Bünzli

If you go with this approach, why wouldn't you just use a map?

~~ Robert.

> let rec get_title ls = match ls with
> | `Title s :: _ -> s
> | _ ::t -> get_title t
> | [] -> raise Not_found (* sucks.. *)
>
>
>   


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
                   ` (4 preceding siblings ...)
  2007-10-17 15:26 ` Zheng Li
@ 2007-10-17 19:59 ` Richard Jones
  2007-10-17 20:24 ` Dario Teixeira
  2007-10-18 15:42 ` Vincent Aravantinos
  7 siblings, 0 replies; 55+ messages in thread
From: Richard Jones @ 2007-10-17 19:59 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list

Sounds a bit like this rather lengthy thread:

http://caml.inria.fr/pub/ml-archives/caml-list/2004/12/a0924032de03d517cb8cb8f2adde6c94.en.html

Rich.

-- 
Richard Jones
Red Hat


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
                   ` (5 preceding siblings ...)
  2007-10-17 19:59 ` [Caml-list] " Richard Jones
@ 2007-10-17 20:24 ` Dario Teixeira
  2007-10-18  7:37   ` Stefano Zacchiroli
  2007-10-18 15:42 ` Vincent Aravantinos
  7 siblings, 1 reply; 55+ messages in thread
From: Dario Teixeira @ 2007-10-17 20:24 UTC (permalink / raw)
  To: caml-list

Hi,

And a big thanks to everyone -- you've really given me a lot of interesting
ideas.  For the time being, I am going for the no-inheritance object solution:
it avoids the option type mess, provides a clean interface to users of the
module, and allows code reuse thanks to OCaml's structural subtyping feature
(the "duck" in this thread's title).  Moreover, while obviously not as concise
as a record, the declaration of each story variant is still quite economical:

class full (id, title, intro, body) =
object
        method id: int = id
        method title: string = title
        method intro: string = intro
        method body: string = body
end

class blurb (id, title, intro) =
object
        method id: int = id
        method title: string = title
        method intro: string = intro
end


Etc, etc.  I can live with this.

Cheers,
Dario





      ___________________________________________________________ 
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 16:21         ` Chris King
@ 2007-10-18  7:28           ` Stefano Zacchiroli
  2007-10-18  8:33             ` [ANN] pa_oo and pa_polymap for 3.10 (Re: [Caml-list] Smells like duck-typing) Jacques Garrigue
  0 siblings, 1 reply; 55+ messages in thread
From: Stefano Zacchiroli @ 2007-10-18  7:28 UTC (permalink / raw)
  To: caml-list

On Wed, Oct 17, 2007 at 12:21:39PM -0400, Chris King wrote:
> See also Jacques' follow up, where he provides a syntax extension for
> these "polymorphic maps" (essentially type-safe property lists):
> http://caml.inria.fr/pub/ml-archives/caml-list/2005/07/314a9eb55585d32e7876ef424f5994ae.fr.html

Do you know if that syntax extension is still working with ocaml/camlp4
3.10?

Thanks for your pointer, Cheers.

-- 
Stefano Zacchiroli -*- PhD in Computer Science ............... now what?
zack@{cs.unibo.it,debian.org,bononia.it} -%- http://www.bononia.it/zack/
(15:56:48)  Zack: e la demo dema ?    /\    All one has to do is hit the
(15:57:15)  Bac: no, la demo scema    \/    right keys at the right time


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 20:24 ` Dario Teixeira
@ 2007-10-18  7:37   ` Stefano Zacchiroli
  2007-10-18 10:31     ` Dario Teixeira
  0 siblings, 1 reply; 55+ messages in thread
From: Stefano Zacchiroli @ 2007-10-18  7:37 UTC (permalink / raw)
  To: caml-list

On Wed, Oct 17, 2007 at 09:24:05PM +0100, Dario Teixeira wrote:
> ideas.  For the time being, I am going for the no-inheritance object solution:

Uhm sorry, why aren't you going for the object *with* inheritance
solution? The one you're proposing here is more lightweight than the
initial one due to the lack of option types, not due to the lack of
inheritance.

Can't you just go for:

  class blurb (id, title, intro) =
  object
          method id: int = id
          method title: string = title
          method intro: string = intro
  end

  class full (id, title, intro, body) =
  object
          inherit blurb (id, title, intro)
          method body: string = body
  end

that way you would also gain code reuse and can maybe define printing
functions on top of each other.

Cheers.

-- 
Stefano Zacchiroli -*- PhD in Computer Science ............... now what?
zack@{cs.unibo.it,debian.org,bononia.it} -%- http://www.bononia.it/zack/
(15:56:48)  Zack: e la demo dema ?    /\    All one has to do is hit the
(15:57:15)  Bac: no, la demo scema    \/    right keys at the right time


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

* [ANN] pa_oo and pa_polymap for 3.10 (Re: [Caml-list] Smells like duck-typing)
  2007-10-18  7:28           ` Stefano Zacchiroli
@ 2007-10-18  8:33             ` Jacques Garrigue
  0 siblings, 0 replies; 55+ messages in thread
From: Jacques Garrigue @ 2007-10-18  8:33 UTC (permalink / raw)
  To: zack; +Cc: caml-list

I've just added versions of pa_oo and pa_polymap working with 3.10.
Sorry for the long delay...

http://www.math.nagoya-u.ac.jp/~garrigue/code/ocaml.html

Jacques Garrigue


From: Stefano Zacchiroli <zack@bononia.it>
> On Wed, Oct 17, 2007 at 12:21:39PM -0400, Chris King wrote:
> > See also Jacques' follow up, where he provides a syntax extension for
> > these "polymorphic maps" (essentially type-safe property lists):
> > http://caml.inria.fr/pub/ml-archives/caml-list/2005/07/314a9eb55585d32e7876ef424f5994ae.fr.html
> 
> Do you know if that syntax extension is still working with ocaml/camlp4
> 3.10?


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18  7:37   ` Stefano Zacchiroli
@ 2007-10-18 10:31     ` Dario Teixeira
  2007-10-18 10:37       ` Stefano Zacchiroli
  2007-10-18 13:28       ` Robert Fischer
  0 siblings, 2 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-18 10:31 UTC (permalink / raw)
  To: Stefano Zacchiroli, caml-list

Hi,

> Uhm sorry, why aren't you going for the object *with* inheritance
> solution? The one you're proposing here is more lightweight than the
> initial one due to the lack of option types, not due to the lack of
> inheritance.
> 
> Can't you just go for:
> 
>   class blurb (id, title, intro) =
>   object
>           method id: int = id
>           method title: string = title
>           method intro: string = intro
>   end
> 
>   class full (id, title, intro, body) =
>   object
>           inherit blurb (id, title, intro)
>           method body: string = body
>   end

While that would indeed involve a little bit of less typing, it's also
conceptually wrong, because a Full story is not a derivation of a Blurb
with an extra field.

Ideally, I should be able to declare a "platonic" Story that includes
all fields that describe a story.  A Full story is just the real-world
clone of the platonic ideal, while a Blurb is a Story with the constraint
that there is no "body" field declared (and so on).

Cheers,
Dario



      ___________________________________________________________ 
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 10:31     ` Dario Teixeira
@ 2007-10-18 10:37       ` Stefano Zacchiroli
  2007-10-18 13:28       ` Robert Fischer
  1 sibling, 0 replies; 55+ messages in thread
From: Stefano Zacchiroli @ 2007-10-18 10:37 UTC (permalink / raw)
  To: caml-list

On Thu, Oct 18, 2007 at 11:31:34AM +0100, Dario Teixeira wrote:
> >   class full (id, title, intro, body) =
> >   object
> >           inherit blurb (id, title, intro)
> >           method body: string = body
> >   end
> 
> While that would indeed involve a little bit of less typing, it's also
> conceptually wrong, because a Full story is not a derivation of a Blurb
> with an extra field.

Well, remember that in ocaml inheritance is not an instance of "is a"
relationship among classes, but rather "method inclusion" (if you really
want a name for this :)). So you can imagine that blurb (or call it
otherwise) is just a set of methods denoting how a blurb-like class
should behave, and here you have back the duck-typing mentioned in the
subject, and than you "inherit" from it both in the actual blurb class
and in the full class.

Just my 0.02€,
Cheers.

-- 
Stefano Zacchiroli -*- PhD in Computer Science ............... now what?
zack@{cs.unibo.it,debian.org,bononia.it} -%- http://www.bononia.it/zack/
(15:56:48)  Zack: e la demo dema ?    /\    All one has to do is hit the
(15:57:15)  Bac: no, la demo scema    \/    right keys at the right time


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 10:31     ` Dario Teixeira
  2007-10-18 10:37       ` Stefano Zacchiroli
@ 2007-10-18 13:28       ` Robert Fischer
  2007-10-18 14:10         ` Dario Teixeira
  1 sibling, 1 reply; 55+ messages in thread
From: Robert Fischer @ 2007-10-18 13:28 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: Stefano Zacchiroli, caml-list


> Ideally, I should be able to declare a "platonic" Story that includes
> all fields that describe a story.  A Full story is just the real-world
> clone of the platonic ideal, while a Blurb is a Story with the constraint
> that there is no "body" field declared (and so on).
>   
That seems backwards from the way OO inheritance is supposed to work.  
You don't go from a more feature-rich case to a less feature-rich case 
-- it's the other way around.

If you s/blurb/header/g or s/blurb/summary/g, then a Full story arguably 
is-a blurb with a body tacked on.

~~ Robert.


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 13:28       ` Robert Fischer
@ 2007-10-18 14:10         ` Dario Teixeira
  2007-10-18 14:18           ` Brian Hurt
                             ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-18 14:10 UTC (permalink / raw)
  To: Robert Fischer; +Cc: Stefano Zacchiroli, caml-list

Hi,

> That seems backwards from the way OO inheritance is supposed to work.  
> You don't go from a more feature-rich case to a less feature-rich case 
> -- it's the other way around.

Of course it is -- that is precisely why inheritance is the wrong
formalism for my problem!  What I need is a "reverse inheritance"
formalism, where a fully defined data structure sits at the root,
and whose descendants are PRUNED versions of the parent.

If sound (and I let the theoreticians decide on that), such a
formalism would be an interesting solution to the type of problem
that originated this thread.

Cheers,
Dario



      ___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
http://uk.answers.yahoo.com/ 


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:10         ` Dario Teixeira
@ 2007-10-18 14:18           ` Brian Hurt
  2007-10-18 14:29             ` Arnaud Spiwack
  2007-10-18 14:58           ` Robert Fischer
  2007-10-18 16:24           ` Dario Teixeira
  2 siblings, 1 reply; 55+ messages in thread
From: Brian Hurt @ 2007-10-18 14:18 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: Robert Fischer, caml-list

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

Dario Teixeira wrote:

>Hi,
>
>  
>
>>That seems backwards from the way OO inheritance is supposed to work.  
>>You don't go from a more feature-rich case to a less feature-rich case 
>>-- it's the other way around.
>>    
>>
>
>Of course it is -- that is precisely why inheritance is the wrong
>formalism for my problem!  What I need is a "reverse inheritance"
>formalism, where a fully defined data structure sits at the root,
>and whose descendants are PRUNED versions of the parent.
>  
>
The problem with this is that it violates one of the assumptions of 
typing, that if type A is (also) a type B, than anywhere you can use a 
type B, you can also use a type A.  This isn't an assumption limited to 
object oriented languages.  And this isn't true in your example- if type 
A is lacking members type B has, then it's possible to write situations 
where a "real" type B can be used, but not a type A- just use a field of 
type B that type A doesn't have.

I think I'd recommend rethinking your approach to the problem.

Brian


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

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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:18           ` Brian Hurt
@ 2007-10-18 14:29             ` Arnaud Spiwack
  2007-10-18 14:45               ` Brian Hurt
  0 siblings, 1 reply; 55+ messages in thread
From: Arnaud Spiwack @ 2007-10-18 14:29 UTC (permalink / raw)
  To: caml-list

Brian Hurt a écrit :
> Dario Teixeira wrote:
>> Hi,
>>
>>   
>>> That seems backwards from the way OO inheritance is supposed to work.  
>>> You don't go from a more feature-rich case to a less feature-rich case 
>>> -- it's the other way around.
>>>     
>>
>> Of course it is -- that is precisely why inheritance is the wrong
>> formalism for my problem!  What I need is a "reverse inheritance"
>> formalism, where a fully defined data structure sits at the root,
>> and whose descendants are PRUNED versions of the parent.
>>   
> The problem with this is that it violates one of the assumptions of 
> typing, that if type A is (also) a type B, than anywhere you can use a 
> type B, you can also use a type A.  This isn't an assumption limited 
> to object oriented languages.  And this isn't true in your example- if 
> type A is lacking members type B has, then it's possible to write 
> situations where a "real" type B can be used, but not a type A- just 
> use a field of type B that type A doesn't have.
>
> I think I'd recommend rethinking your approach to the problem.
Well, what he is suggesting is to be able to derive a supertype A given 
a type B. This is not fundamentaly incorrect. However I fail to find any 
reasoning where it is made use of, in usual mathematics. So I am, 
personnally, a bit puzzled by the suggestion, unable to say if it might 
make sense or not (method exclusion is natural in the setting of 
incomplete objets or traits, but it doesn't fit the situation very much, 
since it usually produces something that requires to be completed).


Arnaud Spiwack


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:29             ` Arnaud Spiwack
@ 2007-10-18 14:45               ` Brian Hurt
  2007-10-18 15:02                 ` Arnaud Spiwack
  2007-10-18 16:22                 ` skaller
  0 siblings, 2 replies; 55+ messages in thread
From: Brian Hurt @ 2007-10-18 14:45 UTC (permalink / raw)
  To: Arnaud Spiwack; +Cc: caml-list

Arnaud Spiwack wrote:

> Brian Hurt a écrit :
>
>> Dario Teixeira wrote:
>>
>>> Hi,
>>>
>>>  
>>>
>>>> That seems backwards from the way OO inheritance is supposed to 
>>>> work.  You don't go from a more feature-rich case to a less 
>>>> feature-rich case -- it's the other way around.
>>>>     
>>>
>>>
>>> Of course it is -- that is precisely why inheritance is the wrong
>>> formalism for my problem!  What I need is a "reverse inheritance"
>>> formalism, where a fully defined data structure sits at the root,
>>> and whose descendants are PRUNED versions of the parent.
>>>   
>>
>> The problem with this is that it violates one of the assumptions of 
>> typing, that if type A is (also) a type B, than anywhere you can use 
>> a type B, you can also use a type A.  This isn't an assumption 
>> limited to object oriented languages.  And this isn't true in your 
>> example- if type A is lacking members type B has, then it's possible 
>> to write situations where a "real" type B can be used, but not a type 
>> A- just use a field of type B that type A doesn't have.
>>
>> I think I'd recommend rethinking your approach to the problem.
>
> Well, what he is suggesting is to be able to derive a supertype A 
> given a type B. This is not fundamentaly incorrect. However I fail to 
> find any reasoning where it is made use of, in usual mathematics. So I 
> am, personnally, a bit puzzled by the suggestion, unable to say if it 
> might make sense or not (method exclusion is natural in the setting of 
> incomplete objets or traits, but it doesn't fit the situation very 
> much, since it usually produces something that requires to be completed).

Saying that A is a supertype of B is the equivelent of saying B is a 
subtype of A.  Same relation, different direction.  In OO lingo, how 
they say "B is a subtype of A" is that "B inherits from (is a subclass 
of) A".

In either case, while all B's are A's, not all A's are B's.  What he 
wants is a case where not all A's are B's, but because of the magic 
mindreading feature of the language (in conjunction with the DWIM 
feature of the hardware), you can treat all A's as B's, with the system 
magically filling in the missing values and methods.  This is what the 
mind reading is needed for- to know how to fill in the missing values.

I will note that Ocaml's row-level polymorphism allows you to invent new 
supertypes of a given subtype as needed (a real nice feature, IMHO).  
But what he's asking for is fundamentally nonsensical.

Brian


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:10         ` Dario Teixeira
  2007-10-18 14:18           ` Brian Hurt
@ 2007-10-18 14:58           ` Robert Fischer
  2007-10-18 15:11             ` William D. Neumann
  2007-10-18 16:24           ` Dario Teixeira
  2 siblings, 1 reply; 55+ messages in thread
From: Robert Fischer @ 2007-10-18 14:58 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: Stefano Zacchiroli, caml-list

[-- Attachment #1: Type: text/html, Size: 1758 bytes --]

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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:45               ` Brian Hurt
@ 2007-10-18 15:02                 ` Arnaud Spiwack
  2007-10-18 15:07                   ` Robert Fischer
  2007-10-18 16:39                   ` skaller
  2007-10-18 16:22                 ` skaller
  1 sibling, 2 replies; 55+ messages in thread
From: Arnaud Spiwack @ 2007-10-18 15:02 UTC (permalink / raw)
  To: caml-list


>
> Saying that A is a supertype of B is the equivelent of saying B is a 
> subtype of A.  Same relation, different direction.  In OO lingo, how 
> they say "B is a subtype of A" is that "B inherits from (is a subclass 
> of) A".
That's not true. That's how you say it in *some* Object Oriented 
languages. Inheritance is a tool which allows you to derive another 
object from another one. You like it to be a subtype though, it usually 
is rather difficult to build a sound inheritance system where it can 
break subtyping anyway (though if you implement the self-type 
specialization in the inheritance but not in the subtyping, it might 
work, but it's unlikely to be what you want to do). Thus, let's say that 
"inheritance is one way to obtain a subtype B out of a type A" (the only 
way in languages such as Java). In OCaml for instance, object types 
exist and subtyping between them. Classes are a mere way to produce 
values of these types, and to provide an inheritance mechanism (which is 
compatible with subtyping).
>
> I will note that Ocaml's row-level polymorphism allows you to invent 
> new supertypes of a given subtype as needed (a real nice feature, 
> IMHO).  But what he's asking for is fundamentally nonsensical.
You don't invent them, they exist. I can't agree to dismiss this 
suggestion without further thought. It might end up being non-sensical, 
maybe not. It merely suggests a way, to derive new values, whose type 
happen to be a supertype of the original one. Why not ? It may be 
considered to the Haskell-like "derive" feature, and such. It is just a 
way to build new values out of known one.


Arnaud Spiwack


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 15:02                 ` Arnaud Spiwack
@ 2007-10-18 15:07                   ` Robert Fischer
  2007-10-18 15:14                     ` Arnaud Spiwack
  2007-10-18 16:39                   ` skaller
  1 sibling, 1 reply; 55+ messages in thread
From: Robert Fischer @ 2007-10-18 15:07 UTC (permalink / raw)
  To: Arnaud Spiwack; +Cc: caml-list


> You don't invent them, they exist. I can't agree to dismiss this 
> suggestion without further thought. It might end up being 
> non-sensical, maybe not. It merely suggests a way, to derive new 
> values, whose type happen to be a supertype of the original one. Why 
> not ? It may be considered to the Haskell-like "derive" feature, and 
> such. It is just a way to build new values out of known one.
>
Formally, can you explain what you're looking for here, and how it's not 
congruent with inheritance?

~~ Robert.


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:58           ` Robert Fischer
@ 2007-10-18 15:11             ` William D. Neumann
  2007-10-18 15:47               ` Loup Vaillant
  2007-10-19 13:08               ` Ed Keith
  0 siblings, 2 replies; 55+ messages in thread
From: William D. Neumann @ 2007-10-18 15:11 UTC (permalink / raw)
  To: Dario Teixeira, Robert Fischer; +Cc: caml-list, Stefano Zacchiroli

On Thu, 18 Oct 2007 09:58:50 -0500, Robert Fischer wrote 

> If you think that a full story as a story with a summary/header,
> and also a body, then you're conceptually into inheritance. 
> 
> From a formal standpoint, you're saying that all full stories
> can be treated as headers/summaries/"blurbs", but not all
> headers/summary/"blurbs" can be treated as full stories. 
> This is equivalent to saying that full stories are a subtype
> of header/summaries/"blurbs".

Well, I think the problem here is that the mental model is reversed with 
respect to the functional model.  Mentally, blurbs are kinds of stories -- 
they are distinguished by their lack of a body.  Using the standard 
inheritance lingo, however, stories are a kind of blurb -- distinguished by 
the inclusion of a body.  Really, it seems like we've got a six of one/half-
dozen of the other situation...

--

William D. Neumann


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 15:07                   ` Robert Fischer
@ 2007-10-18 15:14                     ` Arnaud Spiwack
  0 siblings, 0 replies; 55+ messages in thread
From: Arnaud Spiwack @ 2007-10-18 15:14 UTC (permalink / raw)
  To: caml-list

Robert Fischer a écrit :
>
>> You don't invent them, they exist. I can't agree to dismiss this 
>> suggestion without further thought. It might end up being 
>> non-sensical, maybe not. It merely suggests a way, to derive new 
>> values, whose type happen to be a supertype of the original one. Why 
>> not ? It may be considered to the Haskell-like "derive" feature, and 
>> such. It is just a way to build new values out of known one.
>>
> Formally, can you explain what you're looking for here, and how it's 
> not congruent with inheritance?
>
> ~~ Robert.
Nope. Absolutely not :p . I wouldn't have a clue of what it should 
formally look like, since again I can't find any example of mathematical 
reasoning using that, I have no intuition at all. But it's not 
impossible that there is a good way to make/read such a feature, that's 
just what I am stating.


Arnaud Spiwack


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 13:35 Smells like duck-typing Dario Teixeira
                   ` (6 preceding siblings ...)
  2007-10-17 20:24 ` Dario Teixeira
@ 2007-10-18 15:42 ` Vincent Aravantinos
  7 siblings, 0 replies; 55+ messages in thread
From: Vincent Aravantinos @ 2007-10-18 15:42 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list


Le 17 oct. 07 à 15:35, Dario Teixeira a écrit :

> Hi,
>
> I have been trying to reach a sane modelling in OCaml for a "story"
> data structure in a CMS.

(...)

> b) Use only full_t and make all fields option types.  However, not  
> only is
>    this cumbersome to use, but is also conceptually wrong, because  
> it does
>    not capture the fact that, for example, all "blurb" stories have  
> three
>    *mandatory* fields.

The following uses polymorphic variants for options so as to make  
those fields mandatory (thus it is more safe).

However it remains very cumbersome :)) but I found it interesting  
(and quite funny).

And to follow the current topic, this solution makes inheritance the  
right way (or, at least, the way you want).

But honestly, I don't think it's usable (?)


--------------
(* TYPES *)

type ('a,'b) polyoption = [<`Some of 'a|`None] as 'b

type 'a string_option = (string,[<`None|`Some of string] as 'a)  
polyoption
type 'a int_option    = (int,[<`None|`Some of int] as 'a) polyoption

type some_string = [`Some of string]
type some_int    = [`Some of int]
type nothing     = [`None]

type ('a,'b,'c,'d) t = {
   id:    'a int_option;
   title: 'b string_option;
   intro: 'c string_option;
   body:  'd string_option
}

(* The types we will finally use *)
type full_t  = (some_int, some_string, some_string, some_string) t
type blurp_t = (some_int, some_string, some_string, nothing    ) t
type fresh_t = (nothing , some_string, some_string, some_string) t


(* SOME TESTS *)
let full : full_t = {id = `Some 1; title = `Some "blablax"; intro =  
`Some "blox" ; body = `Some "pouetx"}

   (* Check with a missing field:
   # let badfull : full_t = {id = `None; title = `Some "blablax";  
intro = `Some "blox" ; body = `Some "pouetx"};;
   This expression has type (...)
   *)

let blurp : blurp_t = {id = `Some 2; title = `Some "blablay"; intro =  
`Some "bloy" ; body = `None}
   (* Check with too much fields:
   # let badblurp : blurp_t = {id = `Some 2; title = `Some "blablay";  
intro = `Some "bloy" ; body = `Some "pouety"};;
   This expression has type (...)
   *)

let fresh : fresh_t = {id = `None; title = `Some "blablaz"; intro =  
`Some "bloz" ; body = `Some "pouetz"}

(* FUNCTIONS *)

let get_body : ('a,'b,'c,'d) t -> string = fun x -> let `Some x =  
x.body in x
let get_title : ('a,'b,'c,'d) t -> string = fun x -> let `Some x =  
x.title in x;;

------------------


TESTS:

# get_title full;;
- : string = "blablax"
# get_title blurp;;
- : string = "blablay"
# get_title fresh;;
- : string = "blablaz"
# get_body full;;
- : string = "pouetx"
# get_body blurp;;
This expression has type (...)
# get_body fresh;;
- : string = "pouetz"


Isn't it funny ?

Cheers
Vincent

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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 15:11             ` William D. Neumann
@ 2007-10-18 15:47               ` Loup Vaillant
  2007-10-18 16:08                 ` William D. Neumann
  2007-10-19 13:08               ` Ed Keith
  1 sibling, 1 reply; 55+ messages in thread
From: Loup Vaillant @ 2007-10-18 15:47 UTC (permalink / raw)
  To: William D. Neumann
  Cc: Dario Teixeira, Robert Fischer, caml-list, Stefano Zacchiroli

2007/10/18, William D. Neumann <wneumann@cs.unm.edu>:
> On Thu, 18 Oct 2007 09:58:50 -0500, Robert Fischer wrote
>
> > If you think that a full story as a story with a summary/header,
> > and also a body, then you're conceptually into inheritance.
> >
> > From a formal standpoint, you're saying that all full stories
> > can be treated as headers/summaries/"blurbs", but not all
> > headers/summary/"blurbs" can be treated as full stories.
> > This is equivalent to saying that full stories are a subtype
> > of header/summaries/"blurbs".
>
> Well, I think the problem here is that the mental model is reversed with
> respect to the functional model.  Mentally, blurbs are kinds of stories --
> they are distinguished by their lack of a body.  Using the standard
> inheritance lingo, however, stories are a kind of blurb -- distinguished by
> the inclusion of a body.  Really, it seems like we've got a six of one/half-
> dozen of the other situation...

It feels like the problem is the keyword "inherit". It suggest
C++/Java subtyping, while we just want code reuse. If having stories
inheriting from one another eventually result in less code, I would
consider that cleaner, no matter what "inherit" is supposed to mean.

Sometimes, a tool can be good at something it has not be designed for.
I think this might be the case, here.

Regards,
Loup Vaillant


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 15:47               ` Loup Vaillant
@ 2007-10-18 16:08                 ` William D. Neumann
  0 siblings, 0 replies; 55+ messages in thread
From: William D. Neumann @ 2007-10-18 16:08 UTC (permalink / raw)
  To: Loup Vaillant; +Cc: caml-list, Stefano Zacchiroli

On Thu, 18 Oct 2007 17:47:45 +0200, Loup Vaillant wrote

> It feels like the problem is the keyword "inherit". It suggest
> C++/Java subtyping, while we just want code reuse. If having stories
> inheriting from one another eventually result in less code, I would
> consider that cleaner, no matter what "inherit" is supposed to mean.
> 
> Sometimes, a tool can be good at something it has not be designed 
> for. I think this might be the case, here.

Oh, I absolutely agree there.  And there are a couple of important snippets 
of the manual that seem to apply:

"Note that the relation between object, class and type in Objective Caml is 
very different from that in main stream object-oriented languages like Java 
or C++, so that you should not assume that similar keywords mean the same 
thing." and "Inheritance is a syntactic relation between classes..."


--

William D. Neumann


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

* Re: Smells like duck-typing
  2007-10-17 15:26 ` Zheng Li
@ 2007-10-18 16:13   ` Zheng Li
  2007-10-18 16:37     ` [Caml-list] " William D. Neumann
  0 siblings, 1 reply; 55+ messages in thread
From: Zheng Li @ 2007-10-18 16:13 UTC (permalink / raw)
  To: caml-list


Yet another.

------------------------------------------------------------------------------
class type blurb = 
object method id: int method title:string method intro:string end

class type fresh =
object method title:string method intro:string method body:string end

class type full = object inherit blurb inherit fresh end

class virtual templt = object
  val virtual id: int
  val virtual title: string
  val virtual intro: string
  val virtual body: string
  method id = id
  method title = title
  method intro = intro
  method body = body
end

let blurb (i, t, it) :> blurb = 
object inherit templt val id=i val title=t val intro=it end 

let fresh (t, it, b) :> fresh = 
object inherit templt val title=t val intro=it val body=b end
------------------------------------------------------------------------------

Strangely though, there seems to be a bug in the OO type system: (The solution
proposed above is safe, as it does coercion)

# let coredump = object inherit templt end;;
val coredump : templt = <obj>
# coredump#title;;

Process caml-toplevel segmentation fault


Zheng Li <li@pps.jussieu.fr> writes:
> Hi,
>
> I would vote for the object solution. However, both record and object have
> their own pros and cons. The actual solution should depends on your requirement
> and taste. Just for an example, the following data structure is a possibility:
>
> # type +'a t = {title:string; intro:string; extra:'a} constraint 'a = < .. >;;
> # let fresh (title,intro,(body:string)) = 
>   {title=title; intro=intro; extra=object method body=body end};;
> # let blurb ((id:int),title,intro) =
>   {title=title; intro=intro; extra=object method id=id end};;
> # let print_metadata s = Printf.printf "%d: %s\n" s.extra#id s.title;;
> val print_metadata : < id : int; .. > t -> unit = <fun>
>
> Dario Teixeira <darioteixeira@yahoo.com> writes:
>> I have been trying to reach a sane modelling in OCaml for a "story"
>> data structure in a CMS.  The problem is that I find myself needing
>> a degree of expressiveness that I can't find in the language!  I do
>> have a working, tentative solution, but it has a few ugly aspects
>> that I would very much like to improve.  Details follow.  (Sorry
>> for the long post; at least I hope it's not too dense and hard to
>> follow).
>
> -- 
> Zheng Li
> http://www.pps.jussieu.fr/~li
>
> _______________________________________________
> 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
>

-- 
Zheng Li
http://www.pps.jussieu.fr/~li


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:45               ` Brian Hurt
  2007-10-18 15:02                 ` Arnaud Spiwack
@ 2007-10-18 16:22                 ` skaller
  2007-10-18 16:30                   ` Dario Teixeira
  1 sibling, 1 reply; 55+ messages in thread
From: skaller @ 2007-10-18 16:22 UTC (permalink / raw)
  To: Brian Hurt; +Cc: Arnaud Spiwack, caml-list


On Thu, 2007-10-18 at 10:45 -0400, Brian Hurt wrote:

> I will note that Ocaml's row-level polymorphism allows you to invent new 
> supertypes of a given subtype as needed (a real nice feature, IMHO).  
> But what he's asking for is fundamentally nonsensical.

No it isn't, its just mis-stated. What he actually wants is projections,
which are perfectly sound. That is, given a concrete record with N
fields, a collection of *views* which only expose a subset of the
fields.

More generally, not just a subset of fields, but a new record
which is the image of a epimorphism (a structure preserving
surjection or 'onto' mapping).



-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 14:10         ` Dario Teixeira
  2007-10-18 14:18           ` Brian Hurt
  2007-10-18 14:58           ` Robert Fischer
@ 2007-10-18 16:24           ` Dario Teixeira
  2007-10-18 16:35             ` Vincent Aravantinos
  2007-10-18 16:43             ` Brian Hurt
  2 siblings, 2 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-18 16:24 UTC (permalink / raw)
  To: caml-list

Hi,

(This is a collective reply to all the issues that were raised by my
previous message; sorry if I don't answer each message individually).

I made the early "reverse inheritance" suggestion somewhat facetiously,
but judging from the replies, there was a certain amount of confusion
about what I meant.

I'll try to describe what I have in mind.  I'll do it by modelling
the problem in an imaginary OCaml-derived language that features
"reverse inheritance".  Please read on:


The "story" class is one that is fully defined.  Think of it as a raw
block of marble from which the non-important pieces can be carved out.
To avoid confusion, let's call a class of this kind a "marble-class":

marble-class story (id, title, intro, body) =
object
	method id: int = id
	method title: string = title
	method intro: string = intro
	method body: string = body
end

Now, a "full_story" is one that is also fully defined.  Taking as starting
point the "story" block-class previously defined, you don't need to carve
out anything to obtain a full_story:

marble-class full_story (id, title, intro, body) =
object
	carves story (id, title, intro, body)
end


However, a "blurb_story" does introduce changes: it can be formed by
taking the original story as a starting point, and removing the "body"
chunk of marble.  Note that I am using some new keywords: carves, removes,
and CARVED:

marble-class blurb_story (id, title, intro) =
object
	carves story (id, title, intro, CARVED)
	removes method body
end


Similarly, a "fresh_story" is a story without the "id" field:

marble-class fresh_story (title, intro, body)
object
	carves story (CARVED, title, intro, body)
	removes method id
end


Now, if you think in terms of traditional inheritance, a blurb_story
"B" is also a story "A", and so on (with OCaml's subtyping inheritance,
the semantics are a bit different, but let's not go there right now).
Therefore you would expect that any method that works on A should also
work on B.  But here it's precisely the opposite: anything that works on
B should also work on A, but not the other way around.  If the confusion
is purely linguistic, then let's not call it "reverse inheritance";
let's use "marble carving" instead.  (Note that for these semantics
to be correct, then a carved-class is not allowed to add new methods,
but only to remove existing methods from the class it is carving).

Finally the big question: is this useful or even feasible to implement?
Probably not.  But for the problem I have at hand, this is still the
modelling that best fits my mental picture of the relation between the
various story types.

Cheers,
Dario



      ___________________________________________________________ 
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 16:22                 ` skaller
@ 2007-10-18 16:30                   ` Dario Teixeira
  0 siblings, 0 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-18 16:30 UTC (permalink / raw)
  To: skaller, Brian Hurt; +Cc: caml-list

> No it isn't, its just mis-stated. What he actually wants is projections,
> which are perfectly sound. That is, given a concrete record with N
> fields, a collection of *views* which only expose a subset of the
> fields.
> 
> More generally, not just a subset of fields, but a new record
> which is the image of a epimorphism (a structure preserving
> surjection or 'onto' mapping).
 
Hi,

I wasn't familiar with the "projections" terminology, but that is
precisely what I meant, and what I've referred to as "marble carving"!
(The wheel keeps getting reinvented...)

Incidentally, are projections implemented by any language out there?
(I realise that to a certain extent, SQL views are also projections.
But what about other examples?)

Cheers,
Dario





      ___________________________________________________________ 
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 16:24           ` Dario Teixeira
@ 2007-10-18 16:35             ` Vincent Aravantinos
  2007-10-18 16:43             ` Brian Hurt
  1 sibling, 0 replies; 55+ messages in thread
From: Vincent Aravantinos @ 2007-10-18 16:35 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list


Le 18 oct. 07 à 18:24, Dario Teixeira a écrit :

> Hi,
>
> (This is a collective reply to all the issues that were raised by my
> previous message; sorry if I don't answer each message individually).

(...)

> Finally the big question: is this useful or even feasible to  
> implement?
> Probably not.  But for the problem I have at hand, this is still the
> modelling that best fits my mental picture of the relation between the
> various story types.

Doesn't it much look like what Zheng Li has just posted ?

V.

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

* Re: [Caml-list] Re: Smells like duck-typing
  2007-10-18 16:13   ` Zheng Li
@ 2007-10-18 16:37     ` William D. Neumann
  2007-10-19  0:58       ` Jacques Garrigue
  0 siblings, 1 reply; 55+ messages in thread
From: William D. Neumann @ 2007-10-18 16:37 UTC (permalink / raw)
  To: Zheng Li, caml-list

On Thu, 18 Oct 2007 18:13:05 +0200, Zheng Li wrote

> Strangely though, there seems to be a bug in the OO type system: 
> (The solution proposed above is safe, as it does coercion)
> 
> # let coredump = object inherit templt end;;
> val coredump : templt = <obj>
> # coredump#title;;
> 
> Process caml-toplevel segmentation fault

Hmmm... interesting.  You can apparently create immediate objects with 
virtual instance variables, so long as you don't have virtual methods.

Objective Caml version 3.10.0

# let bad = object method virtual ooops : int end;;
Characters 10-47:
  let bad = object method virtual ooops : int end;;
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This class should be virtual. The following methods are undefined : ooops
# let bad_int = object val virtual x : int method get_x = x end;;
val bad_int : < get_x : int > = <obj>
# let bad_str = object val virtual x : string method get_x = x end;;
val bad_str : < get_x : string > = <obj>
# bad_int # get_x;;
- : int = 0
# bad_str # get_x;;

*boom!*

--

William D. Neumann


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 15:02                 ` Arnaud Spiwack
  2007-10-18 15:07                   ` Robert Fischer
@ 2007-10-18 16:39                   ` skaller
  2007-10-18 16:49                     ` Arnaud Spiwack
  1 sibling, 1 reply; 55+ messages in thread
From: skaller @ 2007-10-18 16:39 UTC (permalink / raw)
  To: Arnaud Spiwack; +Cc: caml-list


On Thu, 2007-10-18 at 17:02 +0200, Arnaud Spiwack wrote:
> >
> > Saying that A is a supertype of B is the equivelent of saying B is a 
> > subtype of A.  Same relation, different direction.  In OO lingo, how 
> > they say "B is a subtype of A" is that "B inherits from (is a subclass 
> > of) A".
> That's not true. That's how you say it in *some* Object Oriented 
> languages. Inheritance is a tool which allows you to derive another 
> object from another one. You like it to be a subtype though, it usually 
> is rather difficult to build a sound inheritance system where it can 
> break subtyping anyway 

That isn't so, almost ALL derived types fail to be subtypes.
In particular, this is always the case when there is a mutator,
because derived values are covariant but mutators are contravariant,
on the other hand Object Orientation intrinsically deals with
mutable state .. QED.

This combination destroys the OO paradigm instantly,
[quite apart from the usual linearity constraint which
make it impossible for OO to handle any kind of relationship]

To understand this simply consider a matrix (base type)
and a symmetric matrix (derived type). Every symmetric
matrix 'is-a' matrix. Fine. It works as a value.

But add a mutator, 'setxy(x,y)' with property that only element x,y
is modified and you're screwed: derived class mutators
work on the base, but not the other way around.

The soundness theory is simple: methods have to be covariant,
but mutators have to be contravariant, and since mutators
are also method they have to be *invariant*, and invariance
effectively means an OO  class cannot have subtypes.

The effect is, given some class type T, the ONLY thing
you are allowed to do with inheritance is implement it,
you cannot actually derive a new type.

[Now someone who understands the theory better than me
can re-explain this ..:]


-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 16:24           ` Dario Teixeira
  2007-10-18 16:35             ` Vincent Aravantinos
@ 2007-10-18 16:43             ` Brian Hurt
  2007-10-18 17:04               ` William D. Neumann
  2007-10-18 17:05               ` Dario Teixeira
  1 sibling, 2 replies; 55+ messages in thread
From: Brian Hurt @ 2007-10-18 16:43 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list

Dario Teixeira wrote:

>Hi,
>
>(This is a collective reply to all the issues that were raised by my
>previous message; sorry if I don't answer each message individually).
>
>I made the early "reverse inheritance" suggestion somewhat facetiously,
>but judging from the replies, there was a certain amount of confusion
>about what I meant.
>
>I'll try to describe what I have in mind.  I'll do it by modelling
>the problem in an imaginary OCaml-derived language that features
>"reverse inheritance".  Please read on:
>
>
>The "story" class is one that is fully defined.  Think of it as a raw
>block of marble from which the non-important pieces can be carved out.
>To avoid confusion, let's call a class of this kind a "marble-class":
>
>marble-class story (id, title, intro, body) =
>object
>	method id: int = id
>	method title: string = title
>	method intro: string = intro
>	method body: string = body
>end
>
>Now, a "full_story" is one that is also fully defined.  Taking as starting
>point the "story" block-class previously defined, you don't need to carve
>out anything to obtain a full_story:
>
>marble-class full_story (id, title, intro, body) =
>object
>	carves story (id, title, intro, body)
>end
>
>
>However, a "blurb_story" does introduce changes: it can be formed by
>taking the original story as a starting point, and removing the "body"
>chunk of marble.  Note that I am using some new keywords: carves, removes,
>and CARVED:
>
>marble-class blurb_story (id, title, intro) =
>object
>	carves story (id, title, intro, CARVED)
>	removes method body
>end
>
>
>Similarly, a "fresh_story" is a story without the "id" field:
>
>marble-class fresh_story (title, intro, body)
>object
>	carves story (CARVED, title, intro, body)
>	removes method id
>end
>
>  
>

So now you've defined full_story, blurb_story, and fresh_story as 
types.  Now, I write:

let get_body (story: full_story) = story#get_body;;

let my_blurb = new blurb_story(id, "A Title", "An Intro");;

let my_body = get_body my_blurb;;

what happens?

Brian


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 16:39                   ` skaller
@ 2007-10-18 16:49                     ` Arnaud Spiwack
  2007-10-18 17:47                       ` skaller
  0 siblings, 1 reply; 55+ messages in thread
From: Arnaud Spiwack @ 2007-10-18 16:49 UTC (permalink / raw)
  To: caml-list

skaller wrote :
> The soundness theory is simple: methods have to be covariant,
> but mutators have to be contravariant, and since mutators
> are also method they have to be *invariant*, and invariance
> effectively means an OO  class cannot have subtypes.
>   
You got that part wrong. I means that subtypes have the same types for 
the same methods (not subtypes, exactly the same types), but it can be 
extended with extra methods (you can be slighlty looser using 
specialisation of the self-type). That's how things work.


And inheritance usually needs to enforce the same invariant condition, 
for the same reasons (since other method inside the inherited class 
could make black-box uses of the overridden method... its type cannot 
change in general). Thus that goes to "generally, all inherited values 
are subtypes" (rational is : if you need to enforce a certain subtyping 
property, it needs to be enforced internally during inheritance as well).


Arnaud Spiwack


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 16:43             ` Brian Hurt
@ 2007-10-18 17:04               ` William D. Neumann
  2007-10-18 17:05               ` Dario Teixeira
  1 sibling, 0 replies; 55+ messages in thread
From: William D. Neumann @ 2007-10-18 17:04 UTC (permalink / raw)
  To: Brian Hurt, Dario Teixeira; +Cc: caml-list

On Thu, 18 Oct 2007 12:43:10 -0400, Brian Hurt wrote

> So now you've defined full_story, blurb_story, and fresh_story as 
> types.  Now, I write:
> 
> let get_body (story: full_story) = story#get_body;;
> 
> let my_blurb = new blurb_story(id, "A Title", "An Intro");;
> 
> let my_body = get_body my_blurb;;
> 
> what happens?

One would assume the same thing that happens if you were to do:

class full_story = object inherit blurb_story val body method body = body 
end;;
let get_body (story: full_story) = story#get_body;;
let my_blurb = new blurb_story(id, "A Title", "An Intro");;
let my_body = get_body my_blurb;;

That is an error indicating that my_body has type < id : int; title : 
string; summary : string > but is used with type < get_body : string ..>, < 
id : int; title : string; summary : string > has no method get_body.

No?

--

William D. Neumann


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 16:43             ` Brian Hurt
  2007-10-18 17:04               ` William D. Neumann
@ 2007-10-18 17:05               ` Dario Teixeira
  2007-10-18 17:22                 ` Brian Hurt
  1 sibling, 1 reply; 55+ messages in thread
From: Dario Teixeira @ 2007-10-18 17:05 UTC (permalink / raw)
  To: Brian Hurt; +Cc: caml-list

> So now you've defined full_story, blurb_story, and fresh_story as 
> types.  Now, I write:
> 
> let get_body (story: full_story) = story#get_body;;
> let my_blurb = new blurb_story(id, "A Title", "An Intro");;
> let my_body = get_body my_blurb;;
> 
> what happens?

Hi,

Well, that's only a problem if you insist in thinking in terms
of inheritance.  Remember that the semantics of marble-carving
are NOT "all that works on full_story should also work on blurb_story",
but the other way around.

Also, imagine you were to add the "get_body" method to the root
"story" class.  The type system in Marble-Caml is smart enough
to tell you that since the blurb_story carved out the "body" field,
then it must also carve out methods that use it.  Aren't imaginary
languages wonderfull?... :-)

(In addition, note that in any real world situation, it wouldn't
make any sense for the user to want to invoke get_body on a blurb
object -- after all, by definition blurbs have no body).

Cheers,
Dario



      ___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
http://uk.answers.yahoo.com/ 


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 17:05               ` Dario Teixeira
@ 2007-10-18 17:22                 ` Brian Hurt
  2007-10-18 17:58                   ` Dario Teixeira
  0 siblings, 1 reply; 55+ messages in thread
From: Brian Hurt @ 2007-10-18 17:22 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: caml-list

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

Dario Teixeira wrote:

>>So now you've defined full_story, blurb_story, and fresh_story as 
>>types.  Now, I write:
>>
>>let get_body (story: full_story) = story#get_body;;
>>let my_blurb = new blurb_story(id, "A Title", "An Intro");;
>>let my_body = get_body my_blurb;;
>>
>>what happens?
>>    
>>
>
>Hi,
>
>Well, that's only a problem if you insist in thinking in terms
>of inheritance.  Remember that the semantics of marble-carving
>are NOT "all that works on full_story should also work on blurb_story",
>but the other way around.
>
>  
>
So all full stories are also blurbs, but blurbs are not full stories.  
So full stories are a more specific type than blurbs are, because while 
we can always use a full story as a blurb, we can't use a blurb as a 
full story.

>Also, imagine you were to add the "get_body" method to the root
>"story" class.  The type system in Marble-Caml is smart enough
>to tell you that since the blurb_story carved out the "body" field,
>then it must also carve out methods that use it.  Aren't imaginary
>languages wonderfull?... :-)
>
>  
>
It's much easier, rather than detecting when things have to be removed, 
to simply detect when things can be added.  Every "remove members" 
relationship can be expressed as an "add members" relationship going the 
other direction.  Start with the simpler (fewer members) type and then 
create the derived type by adding members to make the more complex (more 
members) type.  Anything you can do with one direction of deriving types 
you can do with the other direction of deriving.

Which is why Robert said you had just reinvented inheritance.

>(In addition, note that in any real world situation, it wouldn't
>make any sense for the user to want to invoke get_body on a blurb
>object -- after all, by definition blurbs have no body).
>  
>
Yep.

Brian


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

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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 16:49                     ` Arnaud Spiwack
@ 2007-10-18 17:47                       ` skaller
  2007-10-18 19:55                         ` Robert Fischer
  0 siblings, 1 reply; 55+ messages in thread
From: skaller @ 2007-10-18 17:47 UTC (permalink / raw)
  To: Arnaud Spiwack; +Cc: caml-list


On Thu, 2007-10-18 at 18:49 +0200, Arnaud Spiwack wrote:
> skaller wrote :
> > The soundness theory is simple: methods have to be covariant,
> > but mutators have to be contravariant, and since mutators
> > are also method they have to be *invariant*, and invariance
> > effectively means an OO  class cannot have subtypes.
> >   
> You got that part wrong. I means that subtypes have the same types for 
> the same methods (not subtypes, exactly the same types), but it can be 
> extended with extra methods (you can be slighlty looser using 
> specialisation of the self-type). That's how things work.

I don't think so but I may have misunderstood: 
the problem is, you're thinking of values
again. With a value subtype, the extra invariant adds extra
structure which can admit new interesting theorems, so 
you can add new methods to calculate them.

But that never happens with mutators because you cannot
HAVE any additional invariants. The derived type has
to have exactly the same set of values as the base,
in which case you cannot have any new interesting
methods -- any method you have can always be defined
in terms of the characteristic methods already in
the base (assuming the whole public state is accessible
of course).

Note I am simplifying since real objects are a mix
of mutable and immutable state, in that case
of course you can subtype the immutable state and leave
the mutable state invariant. But that's just factorisation
which complicates the argument.

>From that view point there is actually only ONE possible
mutator: assignment (since, you can always construct the
new state in a new object and assign it, there is no need
for any partial mutators). For example for a mutable
complex number you do not need 'set_real(), set_imaginary()'
mutators, you only need a constructor Cart(r,i) plus assignment.


-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 17:22                 ` Brian Hurt
@ 2007-10-18 17:58                   ` Dario Teixeira
  0 siblings, 0 replies; 55+ messages in thread
From: Dario Teixeira @ 2007-10-18 17:58 UTC (permalink / raw)
  To: Brian Hurt; +Cc: caml-list

Hi,

> So all full stories are also blurbs, but blurbs are not full stories.  
> So full stories are a more specific type than blurbs are, because while 
> we can always use a full story as a blurb, we can't use a blurb as a 
> full story.

Nope, nothing like that.  Read carefully what I wrote: I simply said
that any method that works on a blurb should also work on a full story.
I didn't say anything about reversing the IS-A relation (and yes, I know
that OCaml's inheritance has different semantics, but I am talking here
about OOP in general).

In fact, a blurb is a kind of story.  Just one that has been restricted
such that some of story's fields/methods cannot be used on blurb.  Now
the OOP purists will jump and say that this violates inheritance.  Which
is precisely my point and why I don't call it inheritance!


> It's much easier, rather than detecting when things have to be removed, 
> to simply detect when things can be added.  Every "remove members" 
> relationship can be expressed as an "add members" relationship going the 
> other direction.  Start with the simpler (fewer members) type and then 
> create the derived type by adding members to make the more complex (more 
> members) type.  Anything you can do with one direction of deriving types 
> you can do with the other direction of deriving.

That is true for most problems.  However, I just described one particular
class of problem where it is more natural (and correct if you will) to
derive by deconstruction rather than by construction.

Cheers,
Dario



      ___________________________________________________________ 
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 17:47                       ` skaller
@ 2007-10-18 19:55                         ` Robert Fischer
  0 siblings, 0 replies; 55+ messages in thread
From: Robert Fischer @ 2007-10-18 19:55 UTC (permalink / raw)
  To: skaller; +Cc: Arnaud Spiwack, caml-list


> But that never happens with mutators because you cannot
> HAVE any additional invariants. The derived type has
> to have exactly the same set of values as the base,
> in which case you cannot have any new interesting
> methods -- any method you have can always be defined
> in terms of the characteristic methods already in
> the base (assuming the whole public state is accessible
> of course).
>   
This is why you 1) define a base class which has a very loose set of 
invariants or 2) obscure state from inheriting classes.

~~ Robert.


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

* Re: [Caml-list] Re: Smells like duck-typing
  2007-10-18 16:37     ` [Caml-list] " William D. Neumann
@ 2007-10-19  0:58       ` Jacques Garrigue
  0 siblings, 0 replies; 55+ messages in thread
From: Jacques Garrigue @ 2007-10-19  0:58 UTC (permalink / raw)
  To: wneumann; +Cc: li, caml-list

From: "William D. Neumann" <wneumann@cs.unm.edu>
> On Thu, 18 Oct 2007 18:13:05 +0200, Zheng Li wrote
> 
> > Strangely though, there seems to be a bug in the OO type system: 
> > (The solution proposed above is safe, as it does coercion)
> > 
> > # let coredump = object inherit templt end;;
> > val coredump : templt = <obj>
> > # coredump#title;;
> > 
> > Process caml-toplevel segmentation fault
> 
> Hmmm... interesting.  You can apparently create immediate objects with 
> virtual instance variables, so long as you don't have virtual methods.
> 
> Objective Caml version 3.10.0
> 
> # let bad = object method virtual ooops : int end;;
> Characters 10-47:
>   let bad = object method virtual ooops : int end;;
>             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> This class should be virtual. The following methods are undefined : ooops
> # let bad_int = object val virtual x : int method get_x = x end;;
> val bad_int : < get_x : int > = <obj>
> # let bad_str = object val virtual x : string method get_x = x end;;
> val bad_str : < get_x : string > = <obj>
> # bad_int # get_x;;
> - : int = 0
> # bad_str # get_x;;

Virtual fields are a new and experimental feature in 3.10.
The above bug was fixed shortly after the release.

Jacques Garrigue


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-18 15:11             ` William D. Neumann
  2007-10-18 15:47               ` Loup Vaillant
@ 2007-10-19 13:08               ` Ed Keith
  1 sibling, 0 replies; 55+ messages in thread
From: Ed Keith @ 2007-10-19 13:08 UTC (permalink / raw)
  To: William D. Neumann, Dario Teixeira, Robert Fischer; +Cc: caml-list


--- "William D. Neumann" <wneumann@cs.unm.edu> wrote:

> On Thu, 18 Oct 2007 09:58:50 -0500, Robert Fischer
> wrote 
> 
> > If you think that a full story as a story with a
> summary/header,
> > and also a body, then you're conceptually into
> inheritance. 
> > 
> > From a formal standpoint, you're saying that all
> full stories
> > can be treated as headers/summaries/"blurbs", but
> not all
> > headers/summary/"blurbs" can be treated as full
> stories. 
> > This is equivalent to saying that full stories are
> a subtype
> > of header/summaries/"blurbs".
> 
> Well, I think the problem here is that the mental
> model is reversed with 
> respect to the functional model.  Mentally, blurbs
> are kinds of stories -- 
> they are distinguished by their lack of a body. 
> Using the standard 
> inheritance lingo, however, stories are a kind of
> blurb -- distinguished by 
> the inclusion of a body.  Really, it seems like
> we've got a six of one/half-
> dozen of the other situation...
> 

I'm new to Ocaml, but in C++ the solution would be to
have an abstract base class 'story' and have
'full_story' and 'blurb' inherit from it.

   -EdK

Ed Keith
e_d_k@yahoo.com

Blog: edkeith.blogspot.com

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 


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

* Re: [Caml-list] Smells like duck-typing
  2007-10-17 15:01 ` Dario Teixeira
@ 2007-10-17 20:20   ` Alain Frisch
  0 siblings, 0 replies; 55+ messages in thread
From: Alain Frisch @ 2007-10-17 20:20 UTC (permalink / raw)
  To: Dario Teixeira; +Cc: Francisco Jos? Valverde Albacete, caml-list

Dario Teixeira wrote:
>> To me your problems looks like a good candidate for XML-modelling and 
>> reusing all the tools for working in XML. The more so because XML was 
>> made... exactly for that! Why don't  you give it at least a somewhat 
>> serious thought?
> 
> Hi,
> 
> You mean like CDuce and/or OCamlduce?

I'm not particularly encouraging the use of OCamlduce here, but FWIW, a 
solution would look like:

type title = {{ { title=Latin1 ..} }}
type intro = {{ { intro=Latin1 ..} }}
type blurb_t = {{ { id=Int .. } ++ title ++ intro }}
type fresh_t = {{ { body=Latin1 .. } ++ title ++ intro }}
type full_t = {{ blurb_t & fresh_t }}   (* intersection type *)

let print_metadata s =
   Printf.printf "%d: %s\n" {:s.id:} {:s.title:}

If you're ok duplicating fields, the type definitions can be simplified:

type blurb_t = {{ {id=Int title=Latin1 intro=Latin1 ..} }}
type fresh_t = {{ {body=Latin1 title=Latin1 intro=Latin1 ..} }}
type full_t = {{ {id=Int body=Latin1 title=Latin1 intro=Latin1 ..} }}


-- Alain


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

* Re: [Caml-list] Smells like duck-typing
       [not found] <47161E3B.3060704@tsc.uc3m.es>
@ 2007-10-17 15:01 ` Dario Teixeira
  2007-10-17 20:20   ` Alain Frisch
  0 siblings, 1 reply; 55+ messages in thread
From: Dario Teixeira @ 2007-10-17 15:01 UTC (permalink / raw)
  To: Francisco Jos? Valverde Albacete; +Cc: caml-list

> To me your problems looks like a good candidate for XML-modelling and 
> reusing all the tools for working in XML. The more so because XML was 
> made... exactly for that! Why don't  you give it at least a somewhat 
> serious thought?

Hi,

You mean like CDuce and/or OCamlduce?

Cheers,
Dario



      ___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
http://uk.answers.yahoo.com/ 


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

end of thread, other threads:[~2007-10-19 13:08 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-17 13:35 Smells like duck-typing Dario Teixeira
2007-10-17 14:13 ` [Caml-list] " Arnaud Spiwack
2007-10-17 14:47   ` Dario Teixeira
2007-10-17 14:25 ` Daniel Bünzli
2007-10-17 15:03   ` skaller
2007-10-17 15:13     ` Dario Teixeira
2007-10-17 15:25       ` Arnaud Spiwack
2007-10-17 15:32       ` Daniel Bünzli
2007-10-17 16:21         ` Chris King
2007-10-18  7:28           ` Stefano Zacchiroli
2007-10-18  8:33             ` [ANN] pa_oo and pa_polymap for 3.10 (Re: [Caml-list] Smells like duck-typing) Jacques Garrigue
2007-10-17 16:57         ` [Caml-list] Smells like duck-typing skaller
2007-10-17 16:52       ` skaller
2007-10-17 16:59         ` Robert Fischer
2007-10-17 14:33 ` Chris King
2007-10-17 14:59   ` Dario Teixeira
2007-10-17 15:24 ` Vincent Aravantinos
2007-10-17 15:26 ` Zheng Li
2007-10-18 16:13   ` Zheng Li
2007-10-18 16:37     ` [Caml-list] " William D. Neumann
2007-10-19  0:58       ` Jacques Garrigue
2007-10-17 19:59 ` [Caml-list] " Richard Jones
2007-10-17 20:24 ` Dario Teixeira
2007-10-18  7:37   ` Stefano Zacchiroli
2007-10-18 10:31     ` Dario Teixeira
2007-10-18 10:37       ` Stefano Zacchiroli
2007-10-18 13:28       ` Robert Fischer
2007-10-18 14:10         ` Dario Teixeira
2007-10-18 14:18           ` Brian Hurt
2007-10-18 14:29             ` Arnaud Spiwack
2007-10-18 14:45               ` Brian Hurt
2007-10-18 15:02                 ` Arnaud Spiwack
2007-10-18 15:07                   ` Robert Fischer
2007-10-18 15:14                     ` Arnaud Spiwack
2007-10-18 16:39                   ` skaller
2007-10-18 16:49                     ` Arnaud Spiwack
2007-10-18 17:47                       ` skaller
2007-10-18 19:55                         ` Robert Fischer
2007-10-18 16:22                 ` skaller
2007-10-18 16:30                   ` Dario Teixeira
2007-10-18 14:58           ` Robert Fischer
2007-10-18 15:11             ` William D. Neumann
2007-10-18 15:47               ` Loup Vaillant
2007-10-18 16:08                 ` William D. Neumann
2007-10-19 13:08               ` Ed Keith
2007-10-18 16:24           ` Dario Teixeira
2007-10-18 16:35             ` Vincent Aravantinos
2007-10-18 16:43             ` Brian Hurt
2007-10-18 17:04               ` William D. Neumann
2007-10-18 17:05               ` Dario Teixeira
2007-10-18 17:22                 ` Brian Hurt
2007-10-18 17:58                   ` Dario Teixeira
2007-10-18 15:42 ` Vincent Aravantinos
     [not found] <47161E3B.3060704@tsc.uc3m.es>
2007-10-17 15:01 ` Dario Teixeira
2007-10-17 20:20   ` Alain Frisch

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