[Caml-list] Mutually recursive closures?

2011-09-09 Thread Anthony Tavener
I was considering returning a couple of closures to help organize my UI
code, essentially representing current UI mode by one of these closures. But
then I run into a problem because the types are infinite (returns a
function, which returns a function, ...)

A simplified example:

# let rec a () = printf "state a\n"; b
   and b () = printf "state b\n"; a

Error: This expression has type unit -> unit -> 'a
   but an expression was expected of type 'a


Is there a way I can do this? To express (or 'hide') the cyclic nature of
the type resolution?

I've considered using continuations, but that seems heavy-weight for what
I'm looking to do. And as far as I can tell I'd need to leverage Oleg's
delimcc (which I'd love to start using and wrap my head around -- but for a
task worthy of it!).

I can use a variant to represent states/modes and have a dispatcher which
runs the right code... but this introduces what feels like an unnecessary
layer of distraction. Returning the closure of the "next state" seems
straightforward, but introduces cycles into the typing. :(

I'm hoping I'm missing something simple. Thank-you for any assistance!

 -Tony

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Mutually recursive closures?

2011-09-09 Thread Anthony Tavener
Thanks Jonathan! I've seen -rectypes mentioned over the years and always
glossed over it thinking "Ah, I'll never need that!" :P

Understandable that it's a good default to have disabled. I'll experiment
first and if I like the results I'll try to limit compiling with -rectypes
to the smallest bit of code using it.


On Fri, Sep 9, 2011 at 5:31 PM, Jonathan Protzenko <
jonathan.protze...@gmail.com> wrote:

> You can use equirecursive types, which can be enabled through the -rectypes
> command-line switch. With that option, your example above type-checks.
> However, these are not enabled by default for a variety of reasons, the most
> important one being it makes it much easier to shoot yourself in the foot.
>
> Cheers,
>
> jonathan
>
>
> On Sat 10 Sep 2011 01:14:46 AM CEST, Anthony Tavener wrote:
>
>> I was considering returning a couple of closures to help organize my UI
>> code, essentially representing current UI mode by one of these closures. But
>> then I run into a problem because the types are infinite (returns a
>> function, which returns a function, ...)
>>
>> A simplified example:
>>
>> # let rec a () = printf "state a\n"; b
>>   and b () = printf "state b\n"; a
>>
>> Error: This expression has type unit -> unit -> 'a
>>   but an expression was expected of type 'a
>>
>>
>> Is there a way I can do this? To express (or 'hide') the cyclic nature of
>> the type resolution?
>>
>> I've considered using continuations, but that seems heavy-weight for what
>> I'm looking to do. And as far as I can tell I'd need to leverage Oleg's
>> delimcc (which I'd love to start using and wrap my head around -- but for a
>> task worthy of it!).
>>
>> I can use a variant to represent states/modes and have a dispatcher which
>> runs the right code... but this introduces what feels like an unnecessary
>> layer of distraction. Returning the closure of the "next state" seems
>> straightforward, but introduces cycles into the typing. :(
>>
>> I'm hoping I'm missing something simple. Thank-you for any assistance!
>>
>>  -Tony
>>
>>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Mutually recursive closures?

2011-09-10 Thread Anthony Tavener
That's a good alternative, thanks Philippe! I might use this, but
encapsulate the returned closures with the constructor since they will be of
common type -- whereas the function signatures will be different, some
having additional parameters.

I've read more on rectypes and it's certainly not to be used lightly!


On Sat, Sep 10, 2011 at 12:54 AM, Philippe Veber
wrote:

> You may not need the -rectypes option if you add a thin layer around your
> functions:
>
> Objective Caml version 3.12.1
>
> Findlib has been successfully loaded. Additional directives:
> [...]
> # type t = F of (unit -> t);;
> type t = F of (unit -> t)
> # let rec a = F (fun () -> print_endline "a" ; b)
>   and b = F (fun () -> print_endline "b" ; a);;
> val a : t = F 
> val b : t = F 
> # let ( ! ) (F f) = f ();;
> val ( ! ) : t -> t = 
> # let x1 = ! a;;
> a
> val x1 : t = F 
> # ! x1;;
> b
> - : t = F 
>
> It works in this version because you're defining a brand new type, and not
> using a type alias (like in type t = unit -> t). I think a record would work
> too, but I think either is needed to avoid using -rectypes.
>
> cheers,
>   Philippe.
>
>
>
>
> 2011/9/10 Anthony Tavener 
>
>> Thanks Jonathan! I've seen -rectypes mentioned over the years and always
>> glossed over it thinking "Ah, I'll never need that!" :P
>>
>> Understandable that it's a good default to have disabled. I'll experiment
>> first and if I like the results I'll try to limit compiling with -rectypes
>> to the smallest bit of code using it.
>>
>>
>> On Fri, Sep 9, 2011 at 5:31 PM, Jonathan Protzenko <
>> jonathan.protze...@gmail.com> wrote:
>>
>>> You can use equirecursive types, which can be enabled through the
>>> -rectypes command-line switch. With that option, your example above
>>> type-checks. However, these are not enabled by default for a variety of
>>> reasons, the most important one being it makes it much easier to shoot
>>> yourself in the foot.
>>>
>>> Cheers,
>>>
>>> jonathan
>>>
>>>
>>> On Sat 10 Sep 2011 01:14:46 AM CEST, Anthony Tavener wrote:
>>>
>>>> I was considering returning a couple of closures to help organize my UI
>>>> code, essentially representing current UI mode by one of these closures. 
>>>> But
>>>> then I run into a problem because the types are infinite (returns a
>>>> function, which returns a function, ...)
>>>>
>>>> A simplified example:
>>>>
>>>> # let rec a () = printf "state a\n"; b
>>>>   and b () = printf "state b\n"; a
>>>>
>>>> Error: This expression has type unit -> unit -> 'a
>>>>   but an expression was expected of type 'a
>>>>
>>>>
>>>> Is there a way I can do this? To express (or 'hide') the cyclic nature
>>>> of the type resolution?
>>>>
>>>> I've considered using continuations, but that seems heavy-weight for
>>>> what I'm looking to do. And as far as I can tell I'd need to leverage 
>>>> Oleg's
>>>> delimcc (which I'd love to start using and wrap my head around -- but for a
>>>> task worthy of it!).
>>>>
>>>> I can use a variant to represent states/modes and have a dispatcher
>>>> which runs the right code... but this introduces what feels like an
>>>> unnecessary layer of distraction. Returning the closure of the "next state"
>>>> seems straightforward, but introduces cycles into the typing. :(
>>>>
>>>> I'm hoping I'm missing something simple. Thank-you for any assistance!
>>>>
>>>>  -Tony
>>>>
>>>>
>>
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



[Caml-list] Nested module exposing type from parent?

2011-11-02 Thread Anthony Tavener
I've been struggling with this occasionally...

I'm using nested modules to "open" access to select features of a module.
My problem is I can't find a way to *expose* types in the parent module
through such nested modules.

A simplified example of what I'm looking at:

  module Vec = struct

type t = { x: int; y: int }
let make x y = {x;y}
let add a b = {x=a.x+b.x; y=a.y+b.y}

module Type =
  (* something which has type t = Vec.t,
   * with exposed structure when "open"ed.
   * Also note that Vec is not really an
   * explicit module like this; instead it
   * is implemented in vec.ml *)
  end

Example usage...

  let n = Vec.make 2 5
  open Vec.Type
  let m = {x=1;y=2}
  Vec.add m n


To date, I've defined the type in the Type submodule, which is then used by
the parent module. The unsatisfactory quality of this is that Vec.Type.t is
the "true" type. Ideally the concrete type would live at Vec.t, with "open
Vec.Type" bringing the fields of the type into scope.

As background, here are examples of opening different features of the Vec
module:

  let c = Vec.add a b

  open Vec.Prefixed
  let c = vadd a b

  open Vec.Ops
  let c = a +| b

  open Vec.Type
  let c = Vec.add a {x;y;z=0.}

Apologies if this is really beginner-list material. It's minor, but has
been bugging me.
Thank-you for looking,

 Tony

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Fwd: [Caml-list] Nested module exposing type from parent?

2011-11-02 Thread Anthony Tavener
Oops, I didn't do a group-reply... so in case anyone is interested in what
I ended up with:

-- Forwarded message --
From: Anthony Tavener 
Date: Wed, Nov 2, 2011 at 2:50 PM
Subject: Re: [Caml-list] Nested module exposing type from parent?
To: Vincent Aravantinos 


Actually, better than I initially thought...

I keep this as I have them defined already, except as you said: include
instead of open.

  module Vec = struct
module Type = struct
  type t = { x: int; y: int }
end
include Type
let make x y = {x;y}
let add a b = {x=a.x+b.x; y=a.y+b.y}
  end

Before, I had instead of the include:
  type t = Type.t
  open Type

Which worked, but then the type used everywhere was Vec.Type.t

Thanks again! Simple and effective, and I was looking in all the wrong
places. :)

On Wed, Nov 2, 2011 at 2:36 PM, Anthony Tavener
wrote:

> Thank-you Vincent!
>
> Though this requires a home for the "source type" module, at least the
> types come out right in the end. Thanks!
>
> And this led me to read specifically about include to understand what it
> really does. :)
>
>
> On Wed, Nov 2, 2011 at 2:19 PM, Vincent Aravantinos <
> vincent.aravanti...@gmail.com> wrote:
>
>> **
>> Using "include" instead of "open" would work, ie. turning your example
>> into:
>>
>> module Vec_main = struct
>>
>>   type t = { x: int; y: int }
>>   let make x y = {x;y}
>>   let add a b = {x=a.x+b.x; y=a.y+b.y}
>> end
>>
>> module Vec = struct
>>   include Vec_main
>>   module Type = struct
>> include Vec_main
>> ...
>>   end
>> end
>>
>> Then:
>> # let n = Vec.make 2 5;;
>> val n : Vec.t = {Vec.x = 2; Vec.y = 5}
>> # open Vec.Type;;
>> # let m = {x=1;y=2};;
>> val m : Vec.Type.t = {x = 1; y = 2}
>> # Vec.add m n;;
>> - : Vec.t = {Vec.x = 3; Vec.y = 7}
>>
>> Cheers
>>
>> --
>> Vincent Aravantinos - Postdoctoral Fellow, Concordia University, Hardware 
>> Verification Group
>>
>>
>> On 11/02/2011 03:41 PM, Anthony Tavener wrote:
>>
>> I've been struggling with this occasionally...
>>
>>  I'm using nested modules to "open" access to select features of a
>> module. My problem is I can't find a way to *expose* types in the parent
>> module through such nested modules.
>>
>>  A simplified example of what I'm looking at:
>>
>>module Vec = struct
>>
>>  type t = { x: int; y: int }
>> let make x y = {x;y}
>> let add a b = {x=a.x+b.x; y=a.y+b.y}
>>
>>  module Type =
>>   (* something which has type t = Vec.t,
>>* with exposed structure when "open"ed.
>>* Also note that Vec is not really an
>> * explicit module like this; instead it
>>* is implemented in vec.ml *)
>>   end
>>
>>  Example usage...
>>
>>let n = Vec.make 2 5
>>   open Vec.Type
>>   let m = {x=1;y=2}
>>   Vec.add m n
>>
>>
>>  To date, I've defined the type in the Type submodule, which is then
>> used by the parent module. The unsatisfactory quality of this is that
>> Vec.Type.t is the "true" type. Ideally the concrete type would live at
>> Vec.t, with "open Vec.Type" bringing the fields of the type into scope.
>>
>>  As background, here are examples of opening different features of the
>> Vec module:
>>
>>let c = Vec.add a b
>>
>>open Vec.Prefixed
>>   let c = vadd a b
>>
>>open Vec.Ops
>>   let c = a +| b
>>
>>open Vec.Type
>>   let c = Vec.add a {x;y;z=0.}
>>
>>  Apologies if this is really beginner-list material. It's minor, but has
>> been bugging me.
>> Thank-you for looking,
>>
>>   Tony
>>
>>
>>
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Nested module exposing type from parent?

2011-11-02 Thread Anthony Tavener
I had tried this before, because the first thing I did was run into the
cyclic type due to types being implicitly recursive. And I found that
Janestreet article... I'm sure I felt I had the answer then. But it didn't
work for my needs, because I wanted access to the record fields when
opening the sub-module. This is where Vincent's suggestion of using
'include' made the difference. Thank-you though!


On Wed, Nov 2, 2011 at 5:01 PM, Gabriel Scherer
wrote:

> I see that you solved your problem in a way you find satisfying, but I
> would like to point out that the reason why your original code didn't
> work isn't exactly what you seem to think.
>
> When you define a submodule, the types defined before in the parent
> modules are perfectly accessible and can be referred, just as you
> would do when referring to types defined at the toplevel. You need not
> qualify the type with the outer module name (Vec.t in your example),
> as you are still *inside* this parent module.
>
>  module Vec = struct
>type t = int
>module Type = struct
>  type u = t
>end
>  end
>
>  (1 : Vec.Type.u);;
>
> The problem in your case is that you wish to give the same name to the
> type in Vec and in Vec.Type. This would lead to the following:
>  ... module Type = struct type t = t end ...
>
> But this is ill-defined : it is a recursive type defined as being
> itself. The problem is that the OCaml syntax for type declarations
> always consider them recursive (for values you have "let" and "let
> rec", for types you have "type" which behaves like "type rec" with no
> opt-out way possible). This is a flaw of the OCaml syntax which is
> relatively well-known, see eg. http://ocaml.janestreet.com/?q=node/25
>
> A workaround is to define your inner type "t" in two steps, using an
> different intermediate name to break the cycle:
>
>  module Vec = struct
>type t = int
>module Type = struct
>  type u = t
>  type t = u
>end
>  end
>
>  (1 : Vec.Type.t);;
>
>
> On Wed, Nov 2, 2011 at 10:14 PM, Anthony Tavener
>  wrote:
> > Oops, I didn't do a group-reply... so in case anyone is interested in
> what I
> > ended up with:
> >
> > -- Forwarded message --
> > From: Anthony Tavener 
> > Date: Wed, Nov 2, 2011 at 2:50 PM
> > Subject: Re: [Caml-list] Nested module exposing type from parent?
> > To: Vincent Aravantinos 
> >
> >
> > Actually, better than I initially thought...
> > I keep this as I have them defined already, except as you said: include
> > instead of open.
> >   module Vec = struct
> > module Type = struct
> >   type t = { x: int; y: int }
> > end
> > include Type
> > let make x y = {x;y}
> > let add a b = {x=a.x+b.x; y=a.y+b.y}
> >   end
> > Before, I had instead of the include:
> >   type t = Type.t
> >   open Type
> > Which worked, but then the type used everywhere was Vec.Type.t
> > Thanks again! Simple and effective, and I was looking in all the wrong
> > places. :)
> > On Wed, Nov 2, 2011 at 2:36 PM, Anthony Tavener <
> anthony.tave...@gmail.com>
> > wrote:
> >>
> >> Thank-you Vincent!
> >> Though this requires a home for the "source type" module, at least the
> >> types come out right in the end. Thanks!
> >> And this led me to read specifically about include to understand what it
> >> really does. :)
> >>
> >> On Wed, Nov 2, 2011 at 2:19 PM, Vincent Aravantinos
> >>  wrote:
> >>>
> >>> Using "include" instead of "open" would work, ie. turning your example
> >>> into:
> >>>
> >>> module Vec_main = struct
> >>>   type t = { x: int; y: int }
> >>>   let make x y = {x;y}
> >>>   let add a b = {x=a.x+b.x; y=a.y+b.y}
> >>> end
> >>>
> >>> module Vec = struct
> >>>   include Vec_main
> >>>   module Type = struct
> >>> include Vec_main
> >>> ...
> >>>   end
> >>> end
> >>>
> >>> Then:
> >>> # let n = Vec.make 2 5;;
> >>> val n : Vec.t = {Vec.x = 2; Vec.y = 5}
> >>> # open Vec.Type;;
> >>> # let m = {x=1;y=2};;
> >>> val m : Vec.Type.t = {x = 1; y = 2}
> >>> # Vec.add m n;;
> >>> - : Vec.t = {Vec.x = 3; Vec.y = 7}
> >>>
> >>> Cheers
> >>>
> >>> --
> >>> Vincent Aravantino

Re: [Caml-list] Nested module exposing type from parent?

2011-11-02 Thread Anthony Tavener
Aha! That's more like what I was going for, Martin.

I didn't realize you could equate types in a chain like that, permitting
the definition of structure but also equality to another existing type.
That's good stuff.

This list, and OCaml, often amaze me... solutions keep getting better. :)


On Wed, Nov 2, 2011 at 6:41 PM, Martin Jambon wrote:

> On 11/02/2011 12:41 PM, Anthony Tavener wrote:
> > I've been struggling with this occasionally...
> >
> > I'm using nested modules to "open" access to select features of a
> > module. My problem is I can't find a way to *expose* types in the parent
> > module through such nested modules.
> >
> > A simplified example of what I'm looking at:
> >
> >   module Vec = struct
> >
> > type t = { x: int; y: int }
> > let make x y = {x;y}
> > let add a b = {x=a.x+b.x; y=a.y+b.y}
> >
> > module Type =
> >   (* something which has type t = Vec.t,
> >* with exposed structure when "open"ed.
> >* Also note that Vec is not really an
> >* explicit module like this; instead it
> >* is implemented in vec.ml <http://vec.ml> *)
> >   end
> >
> > Example usage...
> >
> >   let n = Vec.make 2 5
> >   open Vec.Type
> >   let m = {x=1;y=2}
> >   Vec.add m n
>
> I hope I understand the problem correctly.
>
> In order for that code to work, you can do this:
>
> module Vec = struct
>
>  type t = { x: int; y: int }
>  let make x y = {x;y}
>  let add a b = {x=a.x+b.x; y=a.y+b.y}
>
>   module Type = struct
>type t' = t = { x: int; y: int }
>type t = t' = { x: int; y: int }
> (* something which has type t = Vec.t,
> * with exposed structure when "open"ed.
> * Also note that Vec is not really an
> * explicit module like this; instead it
>  * is implemented in vec.ml <http://vec.ml> *)
>  end
> end
>
>
> Or more simply:
>
>
> module Vec = struct
>
>  module Type = struct
> type t = { x: int; y: int }
> (* something which has type t = Vec.t,
> * with exposed structure when "open"ed.
> * Also note that Vec is not really an
> * explicit module like this; instead it
>  * is implemented in vec.ml <http://vec.ml> *)
>  end
>
>  type t = Type.t = { x: int; y: int }
>   let make x y = {x;y}
>  let add a b = {x=a.x+b.x; y=a.y+b.y}
>
> end
>
>
> Now you can open either Vec or Vec.Type and have direct access to the
> record fields.
>
>
> Martin
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] How to fail to install Ocaml in 18 steps

2011-11-16 Thread Anthony Tavener
I saw this as a "user experience report" (as stated), not really asking for
a solution.

The number of different suggestions for how to "install" OCaml has been
quite telling... this is similar to the confusion I find most times I look
for existing libraries: multiple options for similar things with no good
way to tell whats applicable without actually trying them.

People are working on pieces of the "OCaml experience" which are in this
report. I figured the original post was a broadcast in hopes the
appropriate people might glean hints from a fresh user's run through the
rat-maze. If the Norton AV issue is known, and the solution (which I can
agree with) is: kill Norton AV, then maybe some warning for Windows users,
at the site of the binary installer, that this is a known problem and what
the solution is? (Mind you, some people won't have such control over the
machine and have no option but running the local antivirus.) Also, I can
agree that running Linux is an excellent choice... but really, I'm fine
with most of the world running other OS's. Linux becomes like the others
the more widespread it's adoption.

I understand a lot of work has been done to simplify installation, but
sometimes people hit an edge case which sends them spinning into a
nosedive. Ideally a smooth landing can be had regardless of weather
conditions. Some of those edge cases will be found in the wild, by users.

Just my take on it, :)

 Tony



On Wed, Nov 16, 2011 at 6:44 AM, Komtanoo Pinpimai wrote:

> The easiest solution for your situation as of right now would be
> making a vm image that has everything installed, ocaml, eclipse,
> ocaide etc. and distribute it to everybody.
>
> On Tue, Nov 15, 2011 at 4:22 PM, Andrej Bauer 
> wrote:
> > Switching to a different operating system, or running a different
> > operating system in a virtual machine is NOT the most obvious solution
> > to normal people (everyone on this mailing list excluded). While I
> > agree with what Dario says in principle, I am convinced that people
> > aren't that keen on using Gnome/GTK gui inside Virtual box running on
> > a Windows 7.
> >
> > Realistically, there is just no easy way to install Ocaml on Windows
> > from what I've learned.
> >
> > With kind regards,
> >
> > Andrej
> >
> > On Tue, Nov 15, 2011 at 4:28 PM, Dario Teixeira 
> wrote:
> >> Hi,
> >>
> >>> I was shocked to learn that you cannot set it so that it only warns
> >>
> >>> about suspicous files. It actually instists on deleting them! I asked
> >>> my student what Norton will do with his Ph.D. dissertation if it is
> >>> judged to have too low a reputation, and he just faintly smiled. I
> >>> will try to get his boss to buy him a Mac.
> >>
> >> But if switching to a Mac is a solution on the table, that means that
> your
> >> student does not actually need OCaml running on Windows.  What they
> >> need is OCaml, and they just happen to be using Windows as their OS.
> >> However, if this is the case, then it seems you did pick the most
> convoluted
> >> approach.  As others have mentioned, why not just install a
> free-as-in-beer
> >> and easy to use virtualisation software like Virtualbox and use it to
> run a Linux
> >> distro where OCaml is just an apt-get away?
> >>
> >> Mind you, I'm not saying you don't have a point regarding the
> complexity of
> >> installing OCaml on Windows (I wouldn't know).  Nevertheless, it does
> strike me
> >> that you are bending over backwards to avoid what is the most
> straightforward
> >> solution in these cases: run OCaml in a Linux distro.
> >>
> >> Cheers,
> >> Dario Teixeira
> >>
> >
> >
> > --
> > Caml-list mailing list.  Subscription management and archives:
> > https://sympa-roc.inria.fr/wws/info/caml-list
> > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> > Bug reports: http://caml.inria.fr/bin/caml-bugs
> >
> >
>
>
>
> --
> In accordance with U.S. Treasury regulations, if this message contains
> advice concerning one or more Federal tax issues, it is not a formal
> legal opinion and may not be used by any person for the avoidance of
> Federal tax penalties.
>
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] Vim plugin

2012-01-31 Thread Anthony Tavener
Bwahaha! Well that explains why using .annot files didn't seem reliable!

It seemed like it worked any time I *tested* whether it worked, and then
sometime when I try to make practical use of it... no. :P

So, merci beaucoup Pierre! Now I'll make more use of the feature.

 -Tony


2012/1/30 Pierre Vittet 

> [English version below]
>
> Bonjour,
> Je ne sais pas si beaucoup d'entre vous utilise Vim pour coder en OCaml.
> J'ai eu besoin de faire quelques modifications sur le greffon officiel pour
> pouvoir utiliser pleinement les annotations. Je partage donc mes
> modifications pour le cas ou elles soient utiles à d'autres:
> http://www.vim.org/scripts/script.php?script_id=3906.
>
> J'ai corrigé 2 bogues et rajouté une fonctionnalité permettant d'utiliser
> les annotations avec l'ensemble des fichiers .ml ouverts. Jusqu'à présent
> il semble que les annotations ne fonctionnaient que sur le premier fichier
> ouvert.
>
> J'utilise ma version modifiée depuis plusieurs semaines sans problème.
> Si vous essayez mon greffon, je vous remercie de me faire un retour (sur
> les bogues ou leur absence).
>
> Merci
> Pierre Vittet
>
> -
>
> Hello,
> I don't know if many of you use Vim to write OCaml code. I had to make
> some change on the official plugin in order to use the annotation as I
> wanted. I share my modifications in the hope that they can be useful to
> others : http://www.vim.org/scripts/script.php?script_id=3906.
>
> I corrected 2 bugs and add a functionnality allowing to use annotations on
> every .ml file opened in the editor. Until now, it looks like previously
> annotation were working only on the first opened OCaml file.
>
> I use my modified version without any problem for several weeks. If you
> try my plugin, please, keep me informed of the eventual bugs.
>
> Thanks
> Pierre Vittet
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Functional GUI programming: looking for good practices

2012-02-13 Thread Anthony Tavener
I've been taking a stab at this too; for a video game. The approach I'm
taking is with delimited continuations (using Oleg's delimcc). This allows
me to run UI code as a coroutine. The UI code then looks like any other
code, where user inputs are results from a function. Really, the UI code
stops, waiting for input (while the mainline coroutine runs), then returns
the input value.

An example:

let act = user (menu_of_list
  [ ("Equip",`Equip);
("Spell",`Spell);
("End",`End) ] ) in

match act with
| Some `Spell ->
try
  let spellList = (* build a list of casting options for this character
*) in
  let spell = ?.(user (menu_of_list spellList)) in
  let target = ?.(user (select (target_filter spell) scene)) in
  Cast.cast id spell target
with OptionNone -> ()

This example creates a small menu of special options with the given string
labels "Equip", etc. The "user" function is a yield of the UI coroutine,
which means we await resuming with the input value. Interacting with GUI
elements is handled by querying the scene or OpenGL state based on SDL
input events. In this case clicking on the created "Spell" menu item will
return a value of Some `Spell.

Later in the code, more user interactions are handled for providing
specific spell options and then targets. (The "?." prefix operator is just
turning None values into exceptions, to implement user abort.)

I have a yield function, using Delimcc's shift and abort:

let yield level fn =
  shift level (fun k ->
fn k;
abort level () )

which is the basis of the 'user' function in the UI:

  let user fn = yield ui_process fn

So far, I'm not sure how well this works out for a complete project. I like
it so far, but I have complexity growing in some "update loop" stuff, which
are little closures I add to be run each frame-update for reacting to
mouse-over/hover.

I've tried dabbling with FRP, but it kept getting hairy too. I will
probably use it to replace my kludge of "update loop" closures. Someday,
someone will figure out something slick, whether it's a way to use these
tools, or something new. I'm at least happy not using "signals and slots"!

Good luck in the hunt for elegant UI (code)!

 Tony

Inside the UI code, the 'process' delimits the UI coroutine
On Mon, Feb 13, 2012 at 11:13 AM, Raoul Duke  wrote:

> On Mon, Feb 13, 2012 at 3:01 AM, Philippe Veber
>  wrote:
> > than expected, for example with layout management. In order to compute a
> > layout for the widgets, some information has to travel bottom up the
> widget
> > hierarchy, and some goes top down. While there is a well-founded order
> for
>
> academic thoughts from others:
>
> http://lambda-the-ultimate.org/node/2913
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Functional GUI programming: looking for good practices

2012-02-14 Thread Anthony Tavener
Apologies Philippe, this is a bit long...

The "update loop" I mentioned might be a bit of a red-herring, as I'm only
using that for continuously active UI elements: such as changing cursor to
represent the action which would be taken on click. It has nothing to do
with the basic UI flow.

I didn't understand delimcc right away, and I hardly understand it now! :)

I was looking to write UI code much as your example of packing buttons
together with directly bound activation functions.

Here's my "menu_of_list", which takes a list of string * 'a pairs, calling
GUI code to make a menu using the strings as labels, and using the 'a
values as return values...

let menu_of_list lst return =
  (* snipped: preamble which handles positioning, stacking order, getting
font, etc *)
  Gui.add_widget gui
(new Gui.vbox pos stacking spacing
  (lst |> List.map
(fun (label,value) ->
  Gui.wit_fn gui
(new Gui.rectangle_text w h fnt label)
(fun () -> return (Some value) ) )))

The important part here is the "return" function. This will resume the UI
coroutine. It is given to "menu_of_list" by the UI code, then when the GUI
has an activation of a menu button this "return" is called... resuming the
UI where it left off, and with the "Some value" which was associated to the
button.

The magic of how this works is in delimcc capturing portions of the run
stack. Here I've extracted the relevant bits of code:


(* this runs as a coroutine with the "mainline" *)
let ui ui_process () =

  (* in actual code, this menu comes after a "right click", for special
actions *)
  let act = yield ui_process (menu_of_list coord
[ ("Equip",`Equip);
  ("Spell",`Spell);
  ("End",`End) ] ) in
  (* ... handle whatever action the user chose! *)


(* given SDL events, calls activation functions of 'hit' widgets *)
let gui_react gui events =
  let hits = gui_select gui events in
  match hits with
  | h::t -> begin
match get_binding gui h with
| Some f -> f ()  (* runs activation function of widget, such as
"return" to coroutine! *)
| None -> ()
end
  | [] -> ()

let _ =
  (* A prompt is delimcc's mechanism for marking the stack to -limit- the
   * continuation, rather than creating whole-program continuations. *)
  (* So here, the "ui" is initially run, and will *resume* this mainline
continuation
   * at the end of the "user" function call. *)
  let ui_prompt = new_prompt () in
  push_prompt ui_prompt (ui ui_prompt);

  ...

  (* in mainloop *)
gui_react gui events;

--

Now I'm going to restate the yield function here, and try to explain...

let yield level fn =
  shift level (fun k ->
fn k;
abort level () )

"shift" and "abort" are delimcc. This runs the given function "fn" with a
continuation 'k'... so this continuation is the "return" function passed to
menu_of_list, and therefore bound to each menu-button. The abort exits the
"ui coroutine", resuming the mainline, hence the name: yield.

The continuation 'k' comes from the shift... the continuation is the code
"outside" of the shift call... so when it's called (by the mainline's
gui_react), it resume at the end of 'yield' and keep on going... in this
example, handling the returned action!

I hope this conveys at least the gist of what's going on... I read a lot of
papers over-and-over, not understanding... although none were specifically
GUI. Delimited continuations have numerous applications and a surprising
number of configurations for just a pair of functions! (Abort is really a
special case of "reset"... so it's shift and reset, in ump-teen
configurations.)

I'll try to explain if you have any further questions! However, I'm still
trying to sort out how best to write my GUI code -- there is a lot of room
for improvement. :)

 -Tony

PS. I'd like to blame X. Leroy ;)... for a post some 10 years ago replying
to someone's attempt to do a GUI in OCaml... Xavier casually replied
something like "oh, you can use coroutines". That was a wild goose chase
(or Dahu?)! Delimcc didn't exist at the time, and it's native-code
implementation came about just a few years ago (thank-you Oleg!). Even
then, I had no idea how I was supposed to use a coroutine to write GUI
code! Oh well, it was an adventure, and I still don't know if this is a
good thing, but I like it a lot more than "signals and slots" -- the usual
scattered GUI code which is connected by messages/events.


On Tue, Feb 14, 2012 at 3:17 AM, Philippe Veber wrote:

> Hi Anthony,
>
> This looks interesting, however as I'm not very familiar with delimcc
> (that's a shame, I admit), I fail to understand the flow of the program.
> Would you mind giving a snippet of the update loop you mentionned?
>
>
>> So far, I'm not sure how well this works out for a complete project. I
>> like it so far, but I have complexity growing in some "update loop" stuff,
>> which are little closures I add to be run each frame-update for reacting to
>> mouse-over/hover.
>

Re: [Caml-list] Functional GUI programming: looking for good practices

2012-02-14 Thread Anthony Tavener
Hrm... when I re-read my prior post before sending, it made sense. Several
hours later it seems inadequate, and I've thought of something to say more
clearly...

The execution of code bounces between the UI and the mainline. When the
mainline processes a "gui hit" it will resume the UI code *right where it
left off (yielded)*... then the UI will do something and get to another
point where it yields, awaiting input and thereby resuming the mainline
where it was (back to processing gui hits).

Why would I want this? So that I don't have stateful UI code which has to
trickle down to the right place all the time. The UI code is clearer
because it doesn't need to be re-entered from the top each frame. This
suits the declarative style of GUI specification, like the example you
gave, since we don't need special state or messages to communicate what the
GUI is doing. GUI state becomes a property of the... well, the stack. It's
the current scope of the code.

Hope this helps!

 -Tony


On Tue, Feb 14, 2012 at 11:02 AM, Anthony Tavener  wrote:

> Apologies Philippe, this is a bit long...
>
> The "update loop" I mentioned might be a bit of a red-herring, as I'm only
> using that for continuously active UI elements: such as changing cursor to
> represent the action which would be taken on click. It has nothing to do
> with the basic UI flow.
>
> I didn't understand delimcc right away, and I hardly understand it now! :)
>
> I was looking to write UI code much as your example of packing buttons
> together with directly bound activation functions.
>
> Here's my "menu_of_list", which takes a list of string * 'a pairs, calling
> GUI code to make a menu using the strings as labels, and using the 'a
> values as return values...
>
> let menu_of_list lst return =
>   (* snipped: preamble which handles positioning, stacking order, getting
> font, etc *)
>   Gui.add_widget gui
> (new Gui.vbox pos stacking spacing
>   (lst |> List.map
> (fun (label,value) ->
>   Gui.wit_fn gui
> (new Gui.rectangle_text w h fnt label)
> (fun () -> return (Some value) ) )))
>
> The important part here is the "return" function. This will resume the UI
> coroutine. It is given to "menu_of_list" by the UI code, then when the GUI
> has an activation of a menu button this "return" is called... resuming the
> UI where it left off, and with the "Some value" which was associated to the
> button.
>
> The magic of how this works is in delimcc capturing portions of the run
> stack. Here I've extracted the relevant bits of code:
>
>
> (* this runs as a coroutine with the "mainline" *)
> let ui ui_process () =
>
>   (* in actual code, this menu comes after a "right click", for special
> actions *)
>   let act = yield ui_process (menu_of_list coord
> [ ("Equip",`Equip);
>   ("Spell",`Spell);
>   ("End",`End) ] ) in
>   (* ... handle whatever action the user chose! *)
>
>
> (* given SDL events, calls activation functions of 'hit' widgets *)
> let gui_react gui events =
>   let hits = gui_select gui events in
>   match hits with
>   | h::t -> begin
> match get_binding gui h with
> | Some f -> f ()  (* runs activation function of widget, such as
> "return" to coroutine! *)
> | None -> ()
> end
>   | [] -> ()
>
> let _ =
>   (* A prompt is delimcc's mechanism for marking the stack to -limit- the
>* continuation, rather than creating whole-program continuations. *)
>   (* So here, the "ui" is initially run, and will *resume* this mainline
> continuation
>* at the end of the "user" function call. *)
>   let ui_prompt = new_prompt () in
>   push_prompt ui_prompt (ui ui_prompt);
>
>   ...
>
>   (* in mainloop *)
> gui_react gui events;
>
> --
>
> Now I'm going to restate the yield function here, and try to explain...
>
> let yield level fn =
>   shift level (fun k ->
> fn k;
> abort level () )
>
> "shift" and "abort" are delimcc. This runs the given function "fn" with a
> continuation 'k'... so this continuation is the "return" function passed to
> menu_of_list, and therefore bound to each menu-button. The abort exits the
> "ui coroutine", resuming the mainline, hence the name: yield.
>
> The continuation 'k' comes from the shift... the continuation is the code
> "outside" of the shift call... so when it's called (by the mainline's
> gui_react), it 

Re: [Caml-list] OCaml app for iOS, Schnapsen card game

2012-03-21 Thread Anthony Tavener
I think this is awesome. OCaml is much more pleasant to use than the
alternatives, so having it available for developing software on mobile
devices is great, even if it's only iOS. ;)

Your a frontiersman... and I hope others follow suit and write more games
in OCaml and bring it to more mobile platforms!

I've been writing a game for PC with possibility of targeting PS3... and
maybe phones. But I don't even own a phone, so that's not in-mind for now.

I appreciate your work! Even more if I do end up using it!

 Tony

On Wed, Mar 21, 2012 at 4:13 PM, Jeffrey Scofield wrote:

> As more proof that you can write real-world iOS apps in OCaml, our little
> outfit Psellos has just released a second OCaml app through the App Store.
> It plays the classic card games Schnapsen and Sixty-Six.
>
> You can find info about the app at our website:
>
>http://psellos.com/
>
> We think using OCaml was a real advantage in building the game-playing
> engine.  It also seemed a great fit for the animation subsystem that I
> wrote to make the cards move (immutably).
>
> Also, these are great card games.  One of our friends was inspired by
> the app to start up a blog about Schnapsen (also on the website).
>
> In addition to the two apps that we sell (for cheap), I've written 5
> apps that show how to code for iOS in OCaml.  The sources for all 5 are
> available at our website in the OCaml section
> (http://psellos.com/ocaml/).  A few people have used these examples as
> the basis for their own apps.
>
> There's also info on how to cross compile to iOS and to the iOS
> Simulator, how to build the cross compilers we're using, and how to use
> OpenGL ES from OCaml.
>
> Recently there was a question about updating our tools to work with
> Apple's latest Xcode.  Now that the app is released, I'll be doing that
> as soon as I can.
>
> I'm trying my best to start a worldwide OCaml-on-iOS craze :-), and
> would be very happy to hear from anyone interested.
>
> Regards,
>
> Jeffrey Scofield
> Seattle
>
> jeff...@psellos.com
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



[Caml-list] Size of Bigarray elements, or matching with 'kind'?

2012-04-04 Thread Anthony Tavener
I'm trying to determine the size of a Bigarray, in bytes.

I've tried several things... ending up with this as the only solution:

--
let ba_char = Hashtbl.hash Bigarray.char;;
let ba_int8_signed = Hashtbl.hash int8_signed;;
let ba_int8_unsigned = Hashtbl.hash int8_unsigned;;
let ba_int16_signed = Hashtbl.hash int16_signed;;
let ba_int16_unsigned = Hashtbl.hash int16_unsigned;;
let ba_int32 = Hashtbl.hash Bigarray.int32;;
let ba_float32 = Hashtbl.hash float32;;
let ba_int64 = Hashtbl.hash Bigarray.int64;;
let ba_float64 = Hashtbl.hash float64;;
let ba_complex32 = Hashtbl.hash complex32;;
let ba_complex64 = Hashtbl.hash complex64;;
let ba_int = Hashtbl.hash Bigarray.int;;
let ba_nativeint = Hashtbl.hash Bigarray.nativeint;;

let bigarray_bytes ba =
  let elt_bytes = match Hashtbl.hash (Array1.kind ba) with
| x when x=ba_char || x=ba_int8_signed || x=ba_int8_unsigned -> 1
| x when x=ba_int16_signed || x=ba_int16_unsigned-> 2
| x when x=ba_int32 || x=ba_float32  -> 4
| x when x=ba_int64 || x=ba_float64 || x=ba_complex32-> 8
| x when x=ba_complex64  -> 16
| x when x=ba_int || x=ba_nativeint  ->
Nativeint.size lsr 8
| _ -> failwith "Unknown Bigarray kind."
  in (Array1.dim ba) * elt_bytes;;
--

Which is a rather ugly hack! It feels dirty like Obj.magic, while being
completely inelegant, and even has a fail case! Can't get much worse. :)
Of course, internally, bigarray will know it's own size... sometimes the
price of abstraction... *sigh*

I found a related Mantis entry from 6 years back:
http://caml.inria.fr/mantis/view.php?id=3962

Well... does anyone have some better suggestions? Please? :)
Oh, I can make it look a little prettier by plugging in the constants eked
out by Hashtbl.hash. ;D

Why do I want this? Interfacing with OpenGL (glcaml).

Thanks for looking, and more again if you have a good tip!

 -Tony

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Size of Bigarray elements, or matching with 'kind'?

2012-04-05 Thread Anthony Tavener
Ah, yeah. That was an alternative I was considering, though I wasn't sure
how to get the size of nativeint -- now I see: sizeof(value)! :)

Still not the ideal, but probably a little nicer than using 'hash' to
reveal abstracted values. ;)

BTW, thank-you Florent, for your articles on interfacing with C... I know
I've referenced them a few times.


On Thu, Apr 5, 2012 at 11:20 AM, Florent Monnier
wrote:

> Le jeudi 05 avril 2012 07:57:45, Anthony Tavener a écrit :
> > I'm trying to determine the size of a Bigarray, in bytes.
> >
> > I've tried several things... ending up with this as the only solution:
> >
> > --
> > let ba_char = Hashtbl.hash Bigarray.char;;
> > let ba_int8_signed = Hashtbl.hash int8_signed;;
> > let ba_int8_unsigned = Hashtbl.hash int8_unsigned;;
> > let ba_int16_signed = Hashtbl.hash int16_signed;;
> > let ba_int16_unsigned = Hashtbl.hash int16_unsigned;;
> > let ba_int32 = Hashtbl.hash Bigarray.int32;;
> > let ba_float32 = Hashtbl.hash float32;;
> > let ba_int64 = Hashtbl.hash Bigarray.int64;;
> > let ba_float64 = Hashtbl.hash float64;;
> > let ba_complex32 = Hashtbl.hash complex32;;
> > let ba_complex64 = Hashtbl.hash complex64;;
> > let ba_int = Hashtbl.hash Bigarray.int;;
> > let ba_nativeint = Hashtbl.hash Bigarray.nativeint;;
> >
> > let bigarray_bytes ba =
> >   let elt_bytes = match Hashtbl.hash (Array1.kind ba) with
> >
> > | x when x=ba_char || x=ba_int8_signed || x=ba_int8_unsigned -> 1
> > | x when x=ba_int16_signed || x=ba_int16_unsigned-> 2
> > | x when x=ba_int32 || x=ba_float32  -> 4
> > | x when x=ba_int64 || x=ba_float64 || x=ba_complex32-> 8
> > | x when x=ba_complex64  -> 16
> > | x when x=ba_int || x=ba_nativeint  ->
> >
> > Nativeint.size lsr 8
> >
> > | _ -> failwith "Unknown Bigarray kind."
> >
> >   in (Array1.dim ba) * elt_bytes;;
> > --
> >
> > Which is a rather ugly hack! It feels dirty like Obj.magic, while being
> > completely inelegant, and even has a fail case! Can't get much worse. :)
> > Of course, internally, bigarray will know it's own size... sometimes the
> > price of abstraction... *sigh*
> >
> > I found a related Mantis entry from 6 years back:
> > http://caml.inria.fr/mantis/view.php?id=3962
> >
> > Well... does anyone have some better suggestions? Please? :)
> > Oh, I can make it look a little prettier by plugging in the constants
> eked
> > out by Hashtbl.hash. ;D
> >
> > Why do I want this? Interfacing with OpenGL (glcaml).
> >
> > Thanks for looking, and more again if you have a good tip!
>
> Hi Anthony,
>
> Had the same problem with glMLite.
> I use the function below, but if there is a better solution I would be
> interested too:
>
> val ba_sizeof: ba:('a, 'b, Bigarray.c_layout) Bigarray.Array1.t -> int
>
> external elem_size: ba:('a, 'b, Bigarray.c_layout) Bigarray.Array1.t -> int
>  = "ml_ba_elem_size" "noalloc"
>
> let ba_sizeof ~ba =
>  ((Bigarray.Array1.dim ba) * (elem_size ba)) ;;
>
> CAMLprim value ml_ba_elem_size( value _ba )
> {
>struct caml_bigarray *ba = Bigarray_val(_ba);
>int size;
>switch (ba->flags & BIGARRAY_KIND_MASK)
>{
>case BIGARRAY_SINT8:
>case BIGARRAY_UINT8:
>size = 1; break;
>
>case BIGARRAY_SINT16:
>case BIGARRAY_UINT16:
>size = 2; break;
>
>case BIGARRAY_INT32:
>case BIGARRAY_FLOAT32:
>case BIGARRAY_COMPLEX32:
>size = 4; break;
>
>case BIGARRAY_INT64:
>case BIGARRAY_FLOAT64:
>case BIGARRAY_COMPLEX64:
>size = 8; break;
>
>case BIGARRAY_CAML_INT:
>case BIGARRAY_NATIVE_INT:
>size = sizeof(value); break;
>}
>return Val_int(size);
> }
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] using infix operators/functions in modules when not using "open"

2012-04-26 Thread Anthony Tavener
Haoyang Wang provided the answer you're looking for, I think!

In case you are writing your own modules with infix operators, I've found
the following style to be useful:

--- Inside Vector.ml ---
(* definition of some basic functions here... *)
(* now some infix defs using the basic functions, in "Ops" submodule *)
module Ops = struct
  let ( +| ) u v = add u v
  let ( -| ) u v = sub u v
  let ( *| ) a v = scale a v
end
open Ops (* so that they are usable within Vector itself *)
---

--- Some other module without opening all of Vector ---
open Vector.Ops

let answer = a +| b
let same_answer = Vector.add a b
---

In some cases I'll also expose types in a Type submodule. This is to
minimize name-collision with record fields, but have direct access to the
fields in situations which it's appropriate (by doing "open Vector.Type",
for example).

Hope that's of some use!

 -Tony

On Thu, Apr 26, 2012 at 5:01 PM, Haoyang Wang  wrote:

>
> On Apr 26, 2012, at 3:36 PM, ocamllist.robertw...@spamgourmet.com wrote:
>
> > I'm a OCaml newbie.  I don't understand how to use infix functions that
> are in modules when I don't want to use "open".
> >
> > I did discover http://xahlee.org/ocaml/functions.html which explains
> that an infix operator can be used as a prefix.  So, this format:
> >
> >   ((Module.(op)) "foo" "bar")
> >
> > does seem to work.  But, intuitively, it seems like:
> >
> >  "foo" Module.(op) "bar"
> >
> > would work -- it doesn't.
> >
> > Is there a way to keep the infix notation?
> >
> > Thanks.
>
>
> Module.("foo" (op) "bar")
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs