Hello
Here is the latest Caml Weekly News, for the week of November 07 to 14, 2006.
The section 6.6 of OCaml's manual introduces a notion of "Parenthesized patterns". I couldn't find any examples on how to use this feature, and brute-force approach doesn't work: # match 1.0 with (y : float) -> print_float y | (s : string) -> print_string s;; This pattern matches values of type string but is here used to match values of type float # Could anyone point at a suitable resource?Jon Harrop suggested:
I wasn't even aware that you could add type annotations inside a pattern. Your example will not work simply because OCaml's type system will not allow float to unify with string. You need some context where type inference will allow different possibilities, like a tuple containing both a float and a string: # let f = function | (y : float), _ -> print_float y | _, (s : string) -> print_string s;; or a polymorphic variant containing either a float or a string: # let f = function | `F (y : float) -> print_float y | `S (s : string) -> print_string s;; val f : [< `F of float | `S of string ] -> unit = <fun>Lukasz Stafiniak also suggested:
You can do this kind of ad-hoc polymorphism with with G'Caml: http://web.yl.is.s.u-tokyo.ac.jp/~furuse/gcaml/ BTW, I think that G'Caml deserves more attention on this list (see http://lambda-the-ultimate.org/node/1278). (I've even thought that it is still a patch to OCaml 2.0, but it seems to be up-to-date now.) You can check also a related attempt in Meta OCaml, by Oleg Kiselyov: http://pobox.com/~oleg/ftp/ML/gprint/ (search the archives for "Generic print function").Jon Harrop asked and micha answered:
> . Where do you get it from (the CVS doesn't seem to have it)? I did: export CVSROOT=:pserver:anoncvs@camlcvs.inria.fr:/caml cvs login >empty password cvs co -r gcaml3090 ocaml this gives me an ocaml source with gcamllib and README.gcaml... Maybe this is the right source...
Is there any way to get higher-order kinds in Ocaml? While investigating some issues around partial evaluation (in MetaOCaml), we ran across this post from Jacques Guarrigue: http://caml.inria.fr/pub/ml-archives/caml-list/2006/09/05dcdcb7064cc73bfdfb756a419a9010.fr.html After a few emails between Ken Shan and Oleg Kiselyov, Ken produced a very elegant translation of this 'trick' into Haskell, which starts off thus: data T f = Bool (f Bool) | Int (f Int) | Fun (T (F1 f)) newtype F1 f a = F1 { f1 :: T (F2 f a) } newtype F2 f a b = F2 { f2 :: f (a -> b) } Note how f in the above it a type-level function, and the types F1 and F2 are used 'partially applied'. It is possible to expand this all out into first-order, but the end result is not pretty, to say the least! Note that the rest of the Haskell code (classes and instances) can be translated into Functors and Modules [using that nice trick of having functors that produce module types, again thanks to Jacques G.]. The end result is definitely more verbose than the Haskell, but not desperately so. Jacques PS: rest of code, which just implements in an 'open' way what Jacques G. did using closed types in the email linked-to above class Dynamic t where inj :: f t -> T f prj :: T f -> Maybe (f t) instance Dynamic Bool where inj = Bool prj (Bool x) = Just x prj _ = Nothing instance Dynamic Int where inj = Int prj (Int x) = Just x prj _ = Nothing instance (Dynamic a, Dynamic b) => Dynamic (a -> b) where inj x = Fun (inj (F1 (inj (F2 x)))) prj (Fun t) = prj t >>= prj . f1 >>= return . f2 prj _ = Nothing
> Does anyone know why the code generated by camlidl does not use the > CAMLxxx macros that are specified by the OCaml manual? The API for GC root registration went through several design cycles, and CamlIDL was mostly written before the latest API (the CAMLxxx macros) was implemented. Besides, the Begin_roots* macros used in CamlIDL-generated code, while lower-lever than the CAMLxxx macros, are no harder, and maybe slightly simpler, to generate automatically by a program such as CamlIDL.
Haskell people sometimes complain about that OCaml cannot make an arbitrary function infix. For example, they can write (3 `min` 4) to get the result of (min 3 4) in Haskell. Can we satisfy them without changing OCaml's syntax? Here is a simple idea for making a function infix in OCaml. I hope it will be useful for those who like Haskell's backquote notation `function_name`. The idea doesn't require any change of OCaml's syntax. We use the following two infix operators. let ( /* ) x y = y x and ( */ ) x y = x y Then we can make an infix operator /*f*/ for a binary function f. For example, using binary functions 'min' and 'max', we can write 3 /*min*/ 4 + 6 /*max*/ 8 to get 11 as 'min 3 4 + max 5 8'. Note that the infix operator ( */ ) may conflict with Num.( */ ) if the Num module is loaded and opened. You can use other definitions in a similar manner, though. You have to take care of the precedence. For example, 3 /*min*/ 4 * 6 /*max*/ 8 will return 18 as 'max ((min 3 4) * 6) 8'. So we should write (3 /*min*/ 4) * (6 /*max*/ 8) to get 24 as 'min 3 4 * max 6 8'. The original idea was introduced in my blog a few months ago (written in Japanese, though). At that time, I used other definitions: let ( <| ) x y = y x and ( |> ) x y = x y or let ( @^ ) x y = y x and ( ^@ ) x y z = x z y where the definition of ( ^@ ) should be given in a different way because of the precedence of infix operaters starting with '^' or '@'. These operators perform a different behavior because of the precedences of operators. 3 <|min|> 4 + 6 <|max|> 8 (* = max (min 3 (4 + 6)) 8 => 8 *) 3 @^min^@ 4 + 6 @^max^@ 8 (* = min 3 (max (4 + 6) 8) => 3 *) So you have to write (3 <|min|> 4) + (6 <|max|> 8) (3 @^min^@ 4) + (6 @^max^@ 8) to get 11 as min 3 4 + max 5 8'.Till Varoquaux asked and skaller answered:
> I don't really understand the point of the */ operator i your > definition. It's fuy ecause I've cosiderig the same problem recetly ad > came dow to this approach ( I'm redefining(@)... oe c ) > > let ( /* ) x y = y x > > and ( */ ) x y = x y The point is precedence: consider only /* then x /* f y means x /* (f y) whereas x /* f */ y means (f x) y Of course x /* f */ y z means f x (y z) but then x + y z also means (+) x (y z) Also you can write x /* g h */ y which means (g h) x y which is kind of cute, eg: [] /* List.fold_left (fun x y -> y::x) */ [1;2;3]Oleg then added:
Haskell's back-quote notation has a notable limitation as it applies to identifiers only. That is, we gain infix identifiers rather than infix expressions. As it turns out, we can obtain infix expressions without any change of syntax or any backticks: http://www.haskell.org/pipermail/haskell-prime/2006-March/000935.html http://www.haskell.org/haskellwiki/Infix_expressions It seems that the second solution of the above page is similar to the one just proposed for OCaml. For ease of comparison, in Haskell, ($) is defined as [x $ y = x y] and flip flips the order of the arguments. The first solution on that page can be rendered in Ocaml as follows: let (>--) x y = (x,y);; let (<--) (x,f) y = f x y;; Now we can write # 3 >-- min <-- 4;; - : int = 3 We gain not only infix identifiers but infix expressions as well: let a = Array.make 3 'a';; val a : char array = [|'a'; 'a'; 'a'|] 1 >-- Array.set a <-- 'b'; a;; - : char array = [|'a'; 'b'; 'a'|] so we can use even three-argument functions as sort of `infix'...
I'd like to announce that I've released a SOAP server for OCaml. It's available at http://www.caterpillarjones.org/soss An overview follows below, but I should mention two things, one: it's still alpha code, I have not used it extensively yet, and two: it makes extensive use of OCamlduce, which may be of interest to some people here. I hope some people find it of use. Thanks, Stefan Lampe --- SOSS is an implementation of a SOAP server for OCaml. It is designed to allow a service, developed in OCaml, to be made available as a SOAP service with minimal effort. It's features include: It can serve the service through HTTP or TCP It has the option of restricting service functions to sequential access, providing protection to services that are not thread safe. Alternatively, multi threaded access is just as possible RPC style or wrapped document style SOAP messages A generation utility to allow, from the service interface, automatic generation of: Interface routines Message schema WSDL 1.1 WSDL 2.0 (tentative support) It is possible to write a series of service functions in pure OCaml without regard to SOAP and, from the interface file for the service automatically generate all that is required to reveal the service as a SOAP service through HTTP or TCP. It is not, however, a completely general SOAP server. It's goal is as above, to define an OCaml service and reveal it as a SOAP service. As such it provides no support for more general SOAP features, such as SOAP with attachments.Richard Jones said and Stefan Lampe answered:
> Oh interesting. Are you aware of our (cduce-implemented) > SOAP client? http://merjis.com/developers/oc-soap Yes, originally I didn't intend to write a SOAP server, I just wanted to use one - so I looked around for SOAP and OCaml and found OC-SOAP. I then thought I might be able to extend OC-SOAP, but in the end I chose to map from OCaml types to a schema rather than from schema to an OCaml types. For the server side this made more sense, and is nice, in a way... SOSS and OC-SOAP complement each other well. I may soon add a client feature to SOSS, but it will never work with a generic SOAP service, since it will be generated from the OCaml server side interface file - rather than the more public WSDL. It would only provide a solution for an OCaml client with OCaml server where the developers of each are in close contact with each other. For myself though, I only wanted to develop a server side application in OCaml and develop a client in another language - which is why I haven't added this feature yet, though most of the glue is, by default, already written. I think I may have already read in a message somewhere that you recommended CDuce after using it for OC-SOAP, but if anyone else is reading this that is interested in manipulating XML in an OCaml application, I found OCamlduce to be very clear, concise and expressive. I was very impressed.
Here is a quick trick to help you read this CWN if you are viewing it using vim (version 6 or greater).
:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'<1':1
zM
If you know of a better way, please let me know.
If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a look at the archive or the RSS feed of the archives.
If you also wish to receive it every week by mail, you may subscribe online.