Date: Mon, 04 Apr 2005 15:28:18 +0900 (JST) Message-Id: <20050404.152818.74756226.garrigue at math.nagoya-u.ac.jp> To: tim at desert.net Cc: lablgtk at math.nagoya-u.ac.jp Subject: Re: odd type annotation needed; why? From: Jacques Garrigue In-Reply-To: <20050404051740.GB816 at siva.hindu.god> References: <20050404051740.GB816 at siva.hindu.god> Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit From: Tim Smith > I have a simple program here: > > http://www.magnesium.net/~thim/tmp/hello3.ml > > If I compile it as is, it works fine. But I had to add an odd type > annotation to my function, and I know why. My function is: > > let pack_new_button_in_box (box:GPack.box) str = > let button = GButton.button ~label:str ~packing:box#pack () in > ignore (button#connect#clicked ~callback:(clicked str)) > > I call it like: > > let box1 = GPack.hbox ~packing: window#add () in > pack_new_button_in_box box1 "A Button"; > > Why do I need to force the 'box' argument to be of type GPack.box? Why > can't OCaml sort that out on its own? This is due to the presence of optional arguments in the box#pack method. As described in the tutorial, functions taking optional arguments require a type annotation when they are called indirectly (i.e. passed as function arguments for instance). > If I change it to just 'box', then I get this error: > > ocamlc -verbose -I +lablgtk2 lablgtk.cma gtkInit.cmo hello3.ml -o hello3 > File "hello3.ml", line 30, characters 27-31: > This expression has type GPack.box but is here used with type > < pack : GObj.widget -> unit; .. > > Types for method pack are incompatible In the absence of type annotation, looking at the use of box#pack in pack_new_button_in_box, the type checker can only assume that it has type "GObj.widget -> unit", which is incorrect as the actual type is ?from:Gtk.Tags.pack_type -> ?expand:bool -> ?fill:bool -> ?padding:int -> GObj.widget -> unit It is one of the rare (and documented) cases where you have to help the type checker. You can avoid this situation by passing tha packing method alone, as in other lablgtk widgets: let pack_new_button packing label = let button = GButton.button ~label ~packing () in ignore (button#connect#clicked ~callback:(clicked str)) Jacques