Skip to search.

Breaking News Visit Yahoo! News for the latest.

×Close this window

ocaml_beginners · Ocaml Beginners

The Yahoo! Groups Product Blog

Check it out!

Group Information

? Already a member? Sign in to Yahoo!

Yahoo! Groups Tips

Did you know...
Real people. Real stories. See how Yahoo! Groups impacts members worldwide.

Messages

Advanced
Messages Help
Messages 862 - 891 of 13889   Oldest  |  < Older  |  Newer >  |  Newest
Messages: Show Message Summaries Sort by Date ^  
#862 From: "Mike Tikiliainen <mt99@...>" <mt99@...>
Date: Sun Mar 2, 2003 2:44 pm
Subject: weird types with apostrophies
mtikilia
Send Email Send Email
 
Hi,

I'm having problems using the PXP library, but the question is general
enough for anybody I guess. In particular, the problem is with a
function (OK, method but it can easily be a function too)

method write : Pxp_types.output_stream -> Pxp_types.encoding -> unit

Well, I saw this type Pxp_types.output_stream and thought to myself -
"OK, I'll just go look it up in the interface file for Pxp_types, find
out what I need and use it. Pretty trivial so far.

Then, I went to have a look at the interface file and found the
following definition:

type output_stream =
   [ `Out_buffer of Buffer.t
   | `Out_channel of out_channel
   | `Out_function of (string -> int -> int -> unit)
   ]

Then, I thought, "what the hell are those apostrophe things in front
of constructors? Surely they would break because that looks like bad
syntax". I'm still puzzled and hopefully, someone can tell me what
they are and how to use them.

Then I tried some possibilities of what I read in the toploop (with
Pxp loaded correctly):

# Pxp_types.'Out_channel stderr;; (* the "normal" apostrophe *)
Syntax error
# Pxp_types.`Out_channel stderr;;
(* the other one at the topleft of the keyboard, just below ESC-key *)
Syntax error
# Pxp_types.Out_channel stderr;;
(* giving up hope, tried without any apostrophies *)
Unbound constructor Pxp_types.Out_channel

Hey, I have also googled this issue and found a post on the big-scary
Caml-list where the guy uses the damned apostophies everywhere and his
compiler/interpreter seems to be fine with them. The post lives at
http://caml.inria.fr/archives/200204/msg00022.html

I guess there's something major I am missing here, so please help.

'MT` ;)

#863 From: Remi Vanicat <vanicat+egroups@...>
Date: Sun Mar 2, 2003 3:26 pm
Subject: Re: "ocaml_beginners"::[] weird types with apostrophies
dl_ens
Send Email Send Email
 
"Mike Tikiliainen <mt99@...>" <mt99@...> writes:

> Hi,
>
> I'm having problems using the PXP library, but the question is general
> enough for anybody I guess. In particular, the problem is with a
> function (OK, method but it can easily be a function too)
>
> method write : Pxp_types.output_stream -> Pxp_types.encoding -> unit
>
> Well, I saw this type Pxp_types.output_stream and thought to myself -
> "OK, I'll just go look it up in the interface file for Pxp_types, find
> out what I need and use it. Pretty trivial so far.
>
> Then, I went to have a look at the interface file and found the
> following definition:
>
> type output_stream =
>   [ `Out_buffer of Buffer.t
>   | `Out_channel of out_channel
>   | `Out_function of (string -> int -> int -> unit)
>   ]
>
> Then, I thought, "what the hell are those apostrophe things in front
> of constructors? Surely they would break because that looks like bad
> syntax". I'm still puzzled and hopefully, someone can tell me what
> they are and how to use them.

And of course, you I immediately look into the ocaml manual too find
where they speak about it ?
It's describe into the section 4.2 :
http://pauillac.inria.fr/caml/ocaml/htmlman/manual006.html

By the way, there is another difference the [ and ].


>
> Then I tried some possibilities of what I read in the toploop (with
> Pxp loaded correctly):
>
> # Pxp_types.'Out_channel stderr;; (* the "normal" apostrophe *)
> Syntax error
> # Pxp_types.`Out_channel stderr;;
> (* the other one at the topleft of the keyboard, just below ESC-key *)
> Syntax error

`Out_channel stderr will work.

(no open needed).


--
Rémi Vanicat
vanicat@...
http://dept-info.labri.u-bordeaux.fr/~vanicat

#864 From: "William D. Neumann" <wneumann@...>
Date: Tue Mar 4, 2003 4:31 pm
Subject: CocOCaml update (toplevel wrapper for Mac OS X)
wneumann@...
Send Email Send Email
 
Just a tiny update to announce:

CocOCaml v0.6 has been released.  Two small, but important features have
been added to the initial release:
   * The ability to resize the application window.
   * The ability to interrupt the interpreter (Handy for those times when
     you screw up and write an infinite loop.  Not that this ever happens
     to any of us...)

For screen shots, additional information, or downloading the application,
head on over to:
      http://www.cs.unm.edu/~wneumann/cococaml

If you have any questions that can't be answered by the materials at the
web site, feel free to e-mail me.

Requirements:
    Mac OS X 10.2 (might work on earlier releases, but has not been tested)
    A previously installed OCaml distribution
    Knowledge of the path to your OCaml Toplevel executable

Thank you,
William D. Neumann

---

"Well I could be a genius, if I just put my mind to it.
And I...I could do anything, if only I could get 'round to it.
Oh we were brought up on the space-race, now they expect you to clean toilets.
When you've seen how big the world is, how can you make do with this?
If you want me, I'll be sleeping in - sleeping in throughout these glory days."

	 -- Jarvis Cocker

#865 From: Johann Spies <jspies@...>
Date: Wed Mar 5, 2003 10:06 am
Subject: My first CGI program
jspies@...
Send Email Send Email
 
I want to learn to write CGI programs and would appreciate some advice
on where to start, which ocaml libraries to use and where I can find
examples of cgi-programming in ocaml.

I know about the ocamlnet libraries and have read the .mli files but I
would appreciate some examples and a more gentle introduction ...

Regards.
Johann
--
Johann Spies          Telefoon: 021-808 4036
Informasietegnologie, Universiteit van Stellenbosch

      "This is the day which the LORD hath made; we will
       rejoice and be glad in it."           Psalms 118:24

#866 From: oliver@...
Date: Wed Mar 5, 2003 11:25 pm
Subject: Re: "ocaml_beginners"::[] Copying lists, changing it's elements and being astouned how imperative it is!
oliver@...
Send Email Send Email
 
On Sat, Mar 01, 2003 at 03:47:19AM +0100, Remi Vanicat wrote:
> oliver@... writes:
>
> > Hello,
>
> Hello,
>
> >
> >
> > that seems to be absolutely a beginners question,
> > so I'm back to the Ocamlbeginners-mailinglist.
> >
> > Well, here is what I've done:
> >
> > =====================================================
> > oliver@sam:~ > ocaml
> >         Objective Caml version 3.04
> >
> > # let l1 = [ "aaa"; "bbb"; "ccc"];;
> > val l1 : string list = ["aaa"; "bbb"; "ccc"]
> > # let l2 = l1;;
> > val l2 : string list = ["aaa"; "bbb"; "ccc"]
> > # (List.hd l2).[2] <- 'Z';;
> > - : unit = ()
> > # l1;;
> > - : string list = ["aaZ"; "bbb"; "ccc"]
> > # l2;;
> > - : string list = ["aaZ"; "bbb"; "ccc"]
> > #
> > =====================================================
> >
> > Why are _both_ lists changed?
[...]
> > And much more pain and panic creates the next question:
> >
> > Why is it possible to change the list's contents?
> > Shouldn't (List.hd l2) give back a result, which
> > (only the result) is then afterwards changed?
> > (That's, what I think would be functional programming!)
>
> No. functional programming would be to forbid any change. But O'Caml is
> not purely functional, and an example of non functional part are
> string, and in particular string manipulation.


Well, and now I understand, why the bytecodecompiler warns me,
that, when using a string-manipulating function, the function
should have type unit.
I used List.iter instead of List.map for applying the
string-changer and no warnings were printed.

I don't know why, but ocamlc has printed this warning,
even if I had a return-type "string", but have used
string-manipulation (in place changed).
I first had the string as last value in the function
(after a for-loop I added "; name" after the done-statement,
and name was the changed string).


So the function had type string -> string.

Only looking at the types, I would think, that
there will be no warning, because the types
were ok.

But nevertheless the ocamlc told me, that I better should use
a unit-type for that function...

So it has a higher iq than the is necessary for the typesystem.

I had not awaited this.

But step after step I more and more see, what's going on here.



[...]
> > If I would use Arrays here (instead of Lists) then I would
> > be irritated, but not be shocked.
> > Now, where I use lists and can change
>
> The list haven't been changed. They contain exactly the same strings
> (the same block of memory). But this strings have changed.
>
> > them in an imperative way, I'm absolutely confused and shocked and
> > irritated!
> >
> > So, I can create side effects by changing the data in this way?!
>
> changing data are side effect.
>
> When you are doing something like
> (List.hd l2).[2] <- 'Z';;


Well this mail from you is again worth printing on paper
and read it more often and think and rethink about it,
until I got it, what here is going on in Ocaml.

Even if I can write small applications (well, better say
scripts to that minimalistic stuff ;-)) I have many questions
and see, that it's a long way, learning Ocaml.

That it is using different programming paradigms sometimes
is a littlebid confusing.





>
> This doesn't have any useful returned value. The result of this line
> is the modification of a string. This is a side effect.
>
> If you want a side effect free language, try Haskell or Clean.


Well, I had explored Haskell for a while.

And maybe that's, why I'm looking for haskellism here.


Ciao,
    Oliver

#867 From: Remi Vanicat <vanicat+egroups@...>
Date: Thu Mar 6, 2003 2:22 am
Subject: Re: "ocaml_beginners"::[] Copying lists, changing it's elements and being astouned how imperative it is!
dl_ens
Send Email Send Email
 
oliver@... writes:

> On Sat, Mar 01, 2003 at 03:47:19AM +0100, Remi Vanicat wrote:

[...]

>> No. functional programming would be to forbid any change. But O'Caml is
>> not purely functional, and an example of non functional part are
>> string, and in particular string manipulation.
>
>
> Well, and now I understand, why the bytecodecompiler warns me,
> that, when using a string-manipulating function, the function
> should have type unit.

I'm not sure you ave understood.
When you do something as :

   foo bar xux;
   wo um da

the result of the evaluation of foo bar xux is thrown. It is
possible, but strange (you are creating a value, and you throw it).
So ocaml warn you.

You should:

bind the result of the evaluation if you want to use it as in

   let res = foo bar xux in
   wo um da

or explicitly said that you only want the side effect of the function
as in :

   ignore (foo bar xux);
   wo um da

> I used List.iter instead of List.map for applying the
> string-changer and no warnings were printed.

It's normal, you are explicitly doing side effect with a List.iter (or
if it is not a side effect, it is a no-op, so we imagine that it is
side effect).


[...]

> Only looking at the types, I would think, that
> there will be no warning, because the types
> were ok.

warning are not error. The type is correct, but there might be an
error...

[...]

>> > If I would use Arrays here (instead of Lists) then I would
>> > be irritated, but not be shocked.
>> > Now, where I use lists and can change
>>
>> The list haven't been changed. They contain exactly the same strings
>> (the same block of memory). But this strings have changed.
>>
>> > them in an imperative way, I'm absolutely confused and shocked and
>> > irritated!
>> >
>> > So, I can create side effects by changing the data in this way?!
>>
>> changing data are side effect.
>>
>> When you are doing something like
>> (List.hd l2).[2] <- 'Z';;
>
>
> Well this mail from you is again worth printing on paper
> and read it more often and think and rethink about it,
> until I got it, what here is going on in Ocaml.

well more precisely, any function may have an action by two mean :

- by returning value, as in « let f x = x + 1 » Here there is no side
   effect, it's functional programing
- by modifying the state of something, as in « let f x = x.[2] <- 'Z' »
   Here, there the action is not only in returned value (in fact, there
   is nothing interesting there), it is in the modification of an
   already existing value. This is side effect. (Well, there are other
   side effect, for example any I/O function are doing side effect).

[...]


--
Rémi Vanicat
vanicat@...
http://dept-info.labri.u-bordeaux.fr/~vanicat

#868 From: "Nicolas Cannasse" <warplayer@...>
Date: Thu Mar 6, 2003 3:49 am
Subject: Re: "ocaml_beginners"::[] Copying lists, changing it's elements and being astouned how imperative it is!
ncannasse
Send Email Send Email
 
[...]
> You should:
>
> bind the result of the evaluation if you want to use it as in
>
>   let res = foo bar xux in
>   wo um da
>
> or explicitly said that you only want the side effect of the function
> as in :
>
>   ignore (foo bar xux);
>   wo um da

BTW, lots of people use the syntax :

let _ = foo bar xux in
wo um da

instead of ignore, but that's more dangerous, since "ignore" warn you from
partial applications while "let _" doesn't.
and even if something ugly like :

let f x =
     do_some_side_effet;
     (fun y -> something else)

let _ = f x

has *maybe* a meaning, most of the time ignoring results of partial
applications does not make sense.

Nicolas Cannasse

#869 From: oliver@...
Date: Thu Mar 6, 2003 4:29 am
Subject: Re: "ocaml_beginners"::[] Copying lists, changing it's elements and being astouned how imperative it is!
oliver@...
Send Email Send Email
 
On Thu, Mar 06, 2003 at 03:22:27AM +0100, Remi Vanicat wrote:
> oliver@... writes:
>
> > On Sat, Mar 01, 2003 at 03:47:19AM +0100, Remi Vanicat wrote:
>
> [...]
>
> >> No. functional programming would be to forbid any change. But O'Caml is
> >> not purely functional, and an example of non functional part are
> >> string, and in particular string manipulation.
> >
> >
> > Well, and now I understand, why the bytecodecompiler warns me,
> > that, when using a string-manipulating function, the function
> > should have type unit.
>
> I'm not sure you ave understood.
> When you do something as :
>
>   foo bar xux;
>   wo um da
>
> the result of the evaluation of foo bar xux is thrown.

Ooops?

Why this?

I thought, the result of the *last* term is thrown?!


Well, hmhhh...



> It is
> possible, but strange (you are creating a value, and you throw it).

I have looked into the OCaml-Book (O'Reilley) again
today (my printed papers, maybe too old and buggy?),
to clear this fact:


     "The first of hte typically imperative structures is
      the _sequence_. This permist the left-to-righ evaluation
      of a sequence of expressions separated by semicolons.

                +-----------------------+
       Syntax:  | expr_1 ; ... ; expr_n |
                +-----------------------+

      A sequence of expressions is itself an expression,
      whose value is that of the last expresiion in the
      sequence (here expr_n). Nevertheless, all the
      expressions are evaluated, and in particular their
      side-effects are taken into account."

               (Developping Applications with Objective-Caml, page 79)



> So ocaml warn you.
>
> You should:
>
> bind the result of the evaluation if you want to use it as in
>
>   let res = foo bar xux in
>   wo um da

I thought a let-binding is necessary for evaluation-order only
in functional statements?!
If I understand the Ocaml-book correctly, then a
sequence automatically creates a known evaluation-order
via the ";"-syntax.
And when the last term is thrown, I'm right with
my stuff, that I had written...

Or maybe the Ocaml-book is buggy.



#########################################################
let conv_to_valid old_name =
     let name = String.copy old_name in  (* localize in-place-modifikation *)
     let not_enclosed_with a x b =
        not (a <= x & x <= b)
     in
       for i = 0 to String.length name -1
         do
           let c = name.[i] in
           if
             not_enclosed_with 'a' c 'z' &&
             not_enclosed_with 'A' c 'Z' &&
             not_enclosed_with '0' c '9' &&
             c <> '_' && c <> '+' && c <> '-' && c <> ':' && c <> '.'
           then
            name.[i] <- '_';
         done; name
#########################################################

This has type string -> string.

When I throw out the "; name" at the end of this code,
I have type string -> unit


      Do I talking about the same as you do?
      Or did you mean an other aspect of that
      sequence-construct?
      Why should I use a let-statement here?


But nevertheless, when I used it correctly typed,
I got such warnings. Well, to be correct: it was
a code-version before this above code, where I had not
inserted the String.copy, when the compiler showed
my the warning. I have not tested, if the compiler
would throw it again here (with this localized
side-effects).

With the String.copy I wanted to localize the
in-place-modification to that function and therefore
eleminate the side-effects to grab out into the
environment of the function.

Now all modifications are done locally.
So looked from the environment of that function
onto it, it is functional, because no side-effects
on outlier variables/bindeings are done.

I hope you can second this.


(In haskell I think, this trick would not be necessary and
  I (or the language) had to do a complete copy...
  but that's an other story.)






>
> or explicitly said that you only want the side effect of the function
> as in :
>
>   ignore (foo bar xux);
>   wo um da



Well, in another function of the same program/script,
I have this code here:



#####################################################
let file_exists filename =
      try
        ignore (Unix.stat filename) ; true
      with
        Unix.Unix_error(Unix.ENOENT,_,_) -> false
#####################################################

I hope this is accaptable code even for FPL-people.

This function has string -> bool.

But why is ignore necessarily to be used to the first argument?
Is there a problem, when I have to different types in such
a sequence? Is it *this*, what the compiler is worrying
about?



Here again I used, what is mentioned in the O'Reilley
book as "sequence".

It works here.


Will this work always?


>
> > I used List.iter instead of List.map for applying the
> > string-changer and no warnings were printed.
>
> It's normal, you are explicitly doing side effect with a List.iter (or
> if it is not a side effect, it is a no-op, so we imagine that it is
> side effect).

But when the type is string -> string, why does the
bytecodecompiler warns me, that this function should
better be string -> unit?

I mean, when it detects, that I'am doing imperative
stuff, even if the type of my function does not
reflect this, then it is very friendly, that the compiler
tells me that.
On the other hand, it may would be better, if it says
that it's an error, and stops compiling.

(But, as written in my last mail, I didn#t suspected, that
the compiler knows, that it is a side-effecting function, because
it gave me string -> string and so I thought I had "confused"
him. But I had not. (?!))





>
>
> [...]
>
> > Only looking at the types, I would think, that
> > there will be no warning, because the types
> > were ok.
>
> warning are not error. The type is correct, but there might be an
> error...


string -> string
    might be errorneous and should better be
strig -> unit


That is, what the compiler told me.

Do you agree, that it is *this*, what he told me?




>
> [...]
>
> >> > If I would use Arrays here (instead of Lists) then I would
> >> > be irritated, but not be shocked.
> >> > Now, where I use lists and can change
> >>
> >> The list haven't been changed. They contain exactly the same strings
> >> (the same block of memory). But this strings have changed.
> >>
> >> > them in an imperative way, I'm absolutely confused and shocked and
> >> > irritated!
> >> >
> >> > So, I can create side effects by changing the data in this way?!
> >>
> >> changing data are side effect.
> >>
> >> When you are doing something like
> >> (List.hd l2).[2] <- 'Z';;
> >
> >
> > Well this mail from you is again worth printing on paper
> > and read it more often and think and rethink about it,
> > until I got it, what here is going on in Ocaml.
>
> well more precisely, any function may have an action by two mean :
>
> - by returning value, as in « let f x = x + 1 » Here there is no side
>   effect, it's functional programing

OK, I see this.


> - by modifying the state of something, as in « let f x = x.[2] <- 'Z' »
>   Here, there the action is not only in returned value (in fact, there
>   is nothing interesting there), it is in the modification of an
>   already existing value. This is side effect. (Well, there are other
>   side effect, for example any I/O function are doing side effect).

OK, and doing it like in the function above with an

let f x = (String.copy x).[2] <- 'Z'

is imperative/side-effective, but with localized side-effects,
so that it - from the outside of the black box - should
behave like functional code.

(Well this may is not very elegant, and possibly problems
  can creep in here, because I may forget to localize the
  side-effects...)



Ciao,
    Oliver

#870 From: "Nicolas Cannasse" <warplayer@...>
Date: Thu Mar 6, 2003 5:45 am
Subject: Re: "ocaml_beginners"::[] Copying lists, changing it's elements and being astouned how imperative it is!
ncannasse
Send Email Send Email
 
> I thought, the result of the *last* term is thrown?!

Yes, it's true.
But you're evaluating a term which is not used, so if you want to discard
the result you have to tell the compiler that it's really want you want to
do. For example one could write :

List.map print_endline my_list;

but that will alloc and construct a whole list of "unit" elements, which is
useless.
So the compiler warn you have the result of the operation which is
discarded.

You can then remplace by :
List.iter print_endline my_list

Which does not construct a list, and is so more efficient.
( If you put ignore, the function is still called and the result built, but
discarded )

let ignore _ = ()   ( with a warning for partial applications )

Nicolas Cannasse

#871 From: Remi Vanicat <vanicat+egroups@...>
Date: Thu Mar 6, 2003 11:34 am
Subject: Re: "ocaml_beginners"::[] Copying lists, changing it's elements and being astouned how imperative it is!
dl_ens
Send Email Send Email
 
oliver@... writes:

> On Thu, Mar 06, 2003 at 03:22:27AM +0100, Remi Vanicat wrote:
>> oliver@... writes:
>>
>> > On Sat, Mar 01, 2003 at 03:47:19AM +0100, Remi Vanicat wrote:
>>
>> [...]
>>
>> >> No. functional programming would be to forbid any change. But O'Caml is
>> >> not purely functional, and an example of non functional part are
>> >> string, and in particular string manipulation.
>> >
>> >
>> > Well, and now I understand, why the bytecodecompiler warns me,
>> > that, when using a string-manipulating function, the function
>> > should have type unit.
>>
>> I'm not sure you ave understood.
>> When you do something as :
>>
>>   foo bar xux;
>>   wo um da
>>
>> the result of the evaluation of foo bar xux is thrown.
>
> Ooops?
>
> Why this?
>
> I thought, the result of the *last* term is thrown?!

Because of my bad english. I meant discarded, not thrown.
Bye the way, I would say that the result of the last term is returned,
not thrown.

Sorry :(

[...]


>
>
>> So ocaml warn you.
>>
>> You should:
>>
>> bind the result of the evaluation if you want to use it as in
>>
>>   let res = foo bar xux in
>>   wo um da
>
> I thought a let-binding is necessary for evaluation-order only
> in functional statements?!
> If I understand the Ocaml-book correctly, then a
> sequence automatically creates a known evaluation-order
> via the ";"-syntax.

As I said, if you need the returned value you have to bind it.

[...]


> #########################################################
> let conv_to_valid old_name =
>     let name = String.copy old_name in  (* localize in-place-modifikation *)
>     let not_enclosed_with a x b =
>        not (a <= x & x <= b)
>     in
>       for i = 0 to String.length name -1
>         do
>           let c = name.[i] in
>           if
>             not_enclosed_with 'a' c 'z' &&
>             not_enclosed_with 'A' c 'Z' &&
>             not_enclosed_with '0' c '9' &&
>             c <> '_' && c <> '+' && c <> '-' && c <> ':' && c <> '.'
>           then
>            name.[i] <- '_';
>         done; name
> #########################################################
>
> This has type string -> string.

And it is corcet.

>
> When I throw out the "; name" at the end of this code,
> I have type string -> unit

Yes, but your function do some modification on an new string, then do
nothing with this string, so it have no use.

>
>
>      Do I talking about the same as you do?
>      Or did you mean an other aspect of that
>      sequence-construct?
>      Why should I use a let-statement here?

You don't need it here.

>
>
> But nevertheless, when I used it correctly typed,
> I got such warnings. Well, to be correct: it was
> a code-version before this above code, where I had not
> inserted the String.copy, when the compiler showed
> my the warning. I have not tested, if the compiler
> would throw it again here (with this localized
> side-effects).

The warning is not about side effect. It is aboout ';'
sequence. Actually, most (all) of the time ';' sequence do side
effect, but what is important is not sid effect, it is ';'
sequence. You have (often) side effect that are not in ';' sequence,
and then there is no warning.


[...]


>>
>> or explicitly said that you only want the side effect of the function
>> as in :
>>
>>   ignore (foo bar xux);
>>   wo um da
>
>
>
> Well, in another function of the same program/script,
> I have this code here:
>
>
>
> #####################################################
> let file_exists filename =
>      try
>        ignore (Unix.stat filename) ; true
>      with
>        Unix.Unix_error(Unix.ENOENT,_,_) -> false
> #####################################################
>
> I hope this is accaptable code even for FPL-people.
>
> This function has string -> bool.
>
> But why is ignore necessarily to be used to the first argument?
> Is there a problem, when I have to different types in such
> a sequence? Is it *this*, what the compiler is worrying
> about?

when you write « Unix.stat filename; true » you say : compute the stat
of the file, then discadr it and return true. There is a warning
because it seem strange that you have discaded such a computed
value. Bye using the function ingore, you explicitly wrtoe in your
code that you are discarding some value, so there will be no more
warning.

By the way, there is a file_exists function in the module Sys. You
should use it.

[...]


>>
>> > I used List.iter instead of List.map for applying the
>> > string-changer and no warnings were printed.
>>
>> It's normal, you are explicitly doing side effect with a List.iter (or
>> if it is not a side effect, it is a no-op, so we imagine that it is
>> side effect).
>
> But when the type is string -> string, why does the
> bytecodecompiler warns me, that this function should
> better be string -> unit?

Well I have give not exactly the good explanatin. It should be :
you are explicitly doing something which returned valued have no use
with List.iter.

[...]


>
>> - by modifying the state of something, as in « let f x = x.[2] <- 'Z' »
>>   Here, there the action is not only in returned value (in fact, there
>>   is nothing interesting there), it is in the modification of an
>>   already existing value. This is side effect. (Well, there are other
>>   side effect, for example any I/O function are doing side effect).
>
> OK, and doing it like in the function above with an
>
> let f x = (String.copy x).[2] <- 'Z'
>
> is imperative/side-effective, but with localized side-effects,
> so that it - from the outside of the black box - should
> behave like functional code.

Exactly.
Well, it's a no-op function, you should write :

let f x = let cp  = String.copy x in x.[2] <- 'Z'; cp

but you were true.

>
> (Well this may is not very elegant, and possibly problems
>  can creep in here, because I may forget to localize the
>  side-effects...)

One have to use side effect for any efficient string processing. It is
not such a problem.

--
Rémi Vanicat
vanicat@...
http://dept-info.labri.u-bordeaux.fr/~vanicat

#872 From: Jérôme Marant <jmarant@...>
Date: Fri Mar 7, 2003 1:58 pm
Subject: "let _" construct
jmarant@...
Send Email Send Email
 
Hello,

I can't see any reference to the "let _ =" construct in
the OCaml reference manual.

What is its exact meaning? I guess that it executes
immediately instructions within but I've seen it also
within functions.

Thanks.

--
Jérôme Marant <jerome@...>
               <jerome.marant@...>

http://marant.org

#873 From: Remi Vanicat <vanicat+egroups@...>
Date: Fri Mar 7, 2003 2:14 pm
Subject: Re: "ocaml_beginners"::[] "let _" construct
dl_ens
Send Email Send Email
 
Jérôme Marant <jmarant@...> writes:

> Hello,
>
> I can't see any reference to the "let _ =" construct in
> the OCaml reference manual.
>
> What is its exact meaning? I guess that it executes
> immediately instructions within but I've seen it also
> within functions.


It's very easy :
the grammar say that a let is :

let PATERN = EXPR

and _ is a particular pattern that match everything, without binding any
variable.

so

let _ = ....

is the same than

let x = ....

when x is never used after the let (the same hold for let in).

--
Rémi Vanicat
vanicat@...
http://dept-info.labri.u-bordeaux.fr/~vanicat

#874 From: Jérôme Marant <jmarant@...>
Date: Fri Mar 7, 2003 2:32 pm
Subject: Re: "ocaml_beginners"::[] "let _" construct
jmarant@...
Send Email Send Email
 
En réponse à Remi Vanicat <vanicat+egroups@...>:

> Jérôme Marant <jmarant@...> writes:
>
> > Hello,
> >
> > I can't see any reference to the "let _ =" construct in
> > the OCaml reference manual.
> >
> > What is its exact meaning? I guess that it executes
> > immediately instructions within but I've seen it also
> > within functions.
>
>
> It's very easy :
> the grammar say that a let is :
>
> let PATERN = EXPR
>
> and _ is a particular pattern that match everything, without binding
> any
> variable.
>
> so
>
> let _ = ....
>
> is the same than
>
> let x = ....
>
> when x is never used after the let (the same hold for let in).

OK, you confirm what I understood. Thanks.

However, what is the reason for using it in something like:

let a b = something in
   let _ = .... in
   let _ = ....

I've seen it somewhere.


--
Jérôme Marant <jerome@...>
               <jerome.marant@...>

http://marant.org

#875 From: "DUBOIS Fabrice FTRD/DTL/LAN" <fabrice.dubois@...>
Date: Fri Mar 7, 2003 2:34 pm
Subject: RE: "ocaml_beginners"::[] "let _" construct
fabrice.dubois@...
Send Email Send Email
 
Hi,
Yes, use this when you want to call a value-returning function, but without
caring about the value returned. The function is executed, and its result is
lost in the cosmos.
You can as well use the ignore statement that, to my knoledge, is equivalent.
Try out the following :

	 let f x = x+1

then

	 ignore (f 3)


This can help in case you have to specify a sequence of expressions like

	 begin
	   e1; e2;... eN
	 end

... while e2 (for instance) does not return 'unit'. The mechanism then forces e1
to return unit, allowing your sequence to be well-formed (ie., only the last
expression eN is allowed to return a value). Try out the sequence:

	 (f 3);(f 4)
	 --> Warning: this expression should have type unit.

Now let's get rid of the warning:

	 ignore (f 3);(f 4)
	 --> - : int = 5

Regards,
Fabrice Dubois

-----Message d'origine-----
De : Remi Vanicat [mailto:vanicat+egroups@...]
Envoyé : vendredi 7 mars 2003 15:14
À : ocaml_beginners@yahoogroups.com
Objet : Re: "ocaml_beginners"::[] "let _" construct


Jérôme Marant <jmarant@...> writes:

> Hello,
>
> I can't see any reference to the "let _ =" construct in
> the OCaml reference manual.
>
> What is its exact meaning? I guess that it executes
> immediately instructions within but I've seen it also
> within functions.


It's very easy :
the grammar say that a let is :

let PATERN = EXPR

and _ is a particular pattern that match everything, without binding any
variable.

so

let _ = ....

is the same than

let x = ....

when x is never used after the let (the same hold for let in).

--
Rémi Vanicat
vanicat@...
http://dept-info.labri.u-bordeaux.fr/~vanicat


To unsubscribe from this group, send an email to:
ocaml_beginners-unsubscribe@yahoogroups.com
Archives up to 11 October 2002 are also at
http://membres.lycos.fr/ipotesi/OCAML/ocaml-beginners_archive/index.html
The archives of the very official ocaml list (the seniors' one) can be found at
http://caml.inria.fr
Attachments are banned and you're asked to be polite, avoid flames etc. etc.

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/

#876 From: Remi Vanicat <vanicat+egroups@...>
Date: Fri Mar 7, 2003 2:41 pm
Subject: Re: "ocaml_beginners"::[] "let _" construct
dl_ens
Send Email Send Email
 
Jérôme Marant <jmarant@...> writes:

> En réponse à Remi Vanicat <vanicat+egroups@...>:
>
>> Jérôme Marant <jmarant@...> writes:
>>
>> > Hello,
>> >
>> > I can't see any reference to the "let _ =" construct in
>> > the OCaml reference manual.
>> >
>> > What is its exact meaning? I guess that it executes
>> > immediately instructions within but I've seen it also
>> > within functions.
>>
>>
>> It's very easy :
>> the grammar say that a let is :
>>
>> let PATERN = EXPR
>>
>> and _ is a particular pattern that match everything, without binding
>> any
>> variable.
>>
>> so
>>
>> let _ = ....
>>
>> is the same than
>>
>> let x = ....
>>
>> when x is never used after the let (the same hold for let in).
>
> OK, you confirm what I understood. Thanks.
>
> However, what is the reason for using it in something like:
>
> let a b = something in
>   let _ = .... in
>   let _ = ....

There is no good reason. It must better to do

let a b = something in
     .... ;
     ....

Well. There might be some warning, but you should not discard them by
using let _, but by using the ignore function.

--
Rémi Vanicat
vanicat@...
http://dept-info.labri.u-bordeaux.fr/~vanicat

#877 From: Martin Jambon <m.jambon@...>
Date: Fri Mar 7, 2003 2:43 pm
Subject: Re: "ocaml_beginners"::[] My first CGI program
m.jambon@...
Send Email Send Email
 
On Wed, 5 Mar 2003, Johann Spies wrote:

> I want to learn to write CGI programs and would appreciate some advice
> on where to start, which ocaml libraries to use and where I can find
> examples of cgi-programming in ocaml.
>
> I know about the ocamlnet libraries and have read the .mli files but I
> would appreciate some examples and a more gentle introduction ...


[after installing the OCamlNet library]

The most important function is the one to get the arguments :

   Cgi.parse_args ()

returns a list of (name, value).


Before printing the page, output the header:
using:
   Cgi.header "text/html";  (* for HTML, equivalent to "" *)

For plain text:
   Cgi.header "text/plain";

etc.


Some useful rules:
1) do all your computations before printing,
2) catch all exceptions before printing, and print an error page if an
unexpected error occurs, without showing to many data about your
specific system.

Structure of a program:

let get_args () =
   let arg_list = Cgi.parse_args () in
   ... (* check if you got the expected arguments and convert them *)
   (arg1, arg2, ...)  (* returns the data using Caml types *)

let print_error exn =
   Cgi.header "";
   ... (* error message in HTML *)

let generate_data arg1 arg2 ... =
   ...

let print_data data =
   Cgi.header ""; (* or other MIME type *)
   ... (* code that has no chance to generate an exception,
          for printing HTML or other data corresponding to your MIME type *)

let _ =
   let data_ready_to_print =
     try
       let (arg1, arg2, ...) = get_args () in
       generate_data arg1 arg2 ...;
     with exn -> print_error exn in

   print_data data_ready_to_print



Hope this helps,

Martin

#878 From: Jérôme Marant <jmarant@...>
Date: Fri Mar 7, 2003 3:18 pm
Subject: Re: "ocaml_beginners"::[] "let _" construct
jmarant@...
Send Email Send Email
 
En réponse à Remi Vanicat <vanicat+egroups@...>:

> > OK, you confirm what I understood. Thanks.
> >
> > However, what is the reason for using it in something like:
> >
> > let a b = something in
> >   let _ = .... in
> >   let _ = ....
>
> There is no good reason. It must better to do
>
> let a b = something in
>     .... ;
>     ....
>
> Well. There might be some warning, but you should not discard them by
> using let _, but by using the ignore function.

Thank you.

--
Jérôme Marant <jerome@...>
               <jerome.marant@...>

http://marant.org

#879 From: Jérôme Marant <jmarant@...>
Date: Fri Mar 7, 2003 3:19 pm
Subject: RE: "ocaml_beginners"::[] "let _" construct
jmarant@...
Send Email Send Email
 
En réponse à DUBOIS Fabrice FTRD/DTL/LAN <fabrice.dubois@...>:

> Hi,
> Yes, use this when you want to call a value-returning function, but
> without caring about the value returned. The function is executed, and
> its result is lost in the cosmos.
> You can as well use the ignore statement that, to my knoledge, is
> equivalent. Try out the following :
...
> Now let's get rid of the warning:
>
>  ignore (f 3);(f 4)
>  --> - : int = 5

Thank you.

--
Jérôme Marant <jerome@...>
               <jerome.marant@...>

http://marant.org

#880 From: Stalkern 2 <stalkern2@...>
Date: Sat Mar 8, 2003 12:38 am
Subject: ocamlfind and ocaml -pthreads
stalkern2
Send Email Send Email
 
Hello to everybody

I've recompiled a copy of ocaml 3.0.6 with the -pthreads option, and then
tried several times to recompile ocamlfind, but both findlib-0.7.2 and
findlib-0.8.1 stop seeing META files that are at their level, even after a
fresh install of the ocamlfind.conf file.

I was used to perform installs starting ocamlfind at the place where the META
of the package to install was, generally the same as the place where I
compiled from

Why so?



Here are more infos. I'm running a RH8.0

$ which ocamlopt
/usr/local/bin/ocamlopt


$ ocamlfind printconf
Effective configuration:
Configuration file:
     /usr/local/etc/ocamlfind.conf
Search path:
     /usr/local/lib/ocaml/site-lib
Packages will be installed in/removed from:
     /usr/local/lib/ocaml/site-lib
META files will be installed in/removed from:
     the corresponding package directories
The standard library is assumed to reside in:
     /usr/local/lib/ocaml
The ld.conf file can be found here:
     /usr/local/lib/ocaml/ld.conf


Thank you for any hint

Ernesto

#881 From: Johann Spies <jspies@...>
Date: Mon Mar 10, 2003 10:55 am
Subject: Re: "ocaml_beginners"::[] My first CGI program
jspies@...
Send Email Send Email
 
On Fri, Mar 07, 2003 at 03:43:46PM +0100, Martin Jambon wrote:

> [after installing the OCamlNet library]
...

> Hope this helps,

Thanks Martin.  It does help indeed!

I would like to confirm my understanding of something (which is not
strictly ocaml, but rather html):  Am I correct in assuming that the
datatype multipart/form-data creates a stream if the field is of the
type "file"?  So when I want to upload a file then ocaml has to read
the stream and create a file (or files) locally?

Regards
Johann
--
Johann Spies          Telefoon: 021-808 4036
Informasietegnologie, Universiteit van Stellenbosch

      "What good is it, my brothers, if a man claims to have
       faith, but has no deeds? Can such faith save him?
       Suppose a brother or sister is without clothes and
       daily food.   If one of you says to him, "Go, I wish
       you well; keep warm and well fed," but does nothing
       about his physical needs, what good is it? In the same
       way, faith by itself, if it is not accompanied by
       actions, is dead."          James 2:14-17

#882 From: Stalkern 2 <stalkern2@...>
Date: Mon Mar 10, 2003 11:09 am
Subject: Re: "ocaml_beginners"::[] ocamlfind and ocaml -pthreads
stalkern2
Send Email Send Email
 
Il  Saturday 08 March 2003 01:38, Stalkern 2 ha scritto:
>  Hello to everybody
>
> I've recompiled a copy of ocaml 3.0.6 with the -pthreads option, and then
> tried several times to recompile ocamlfind, but both findlib-0.7.2 and
> findlib-0.8.1 stop seeing META files that are at their level, even after a
> fresh install of the ocamlfind.conf file.
>
> I was used to perform installs starting ocamlfind at the place where the
> META of the package to install was, generally the same as the place where I
> compiled from
>
> Why so?

OK, I don't know how did that work before but NOW it's right.
When you use a library that is not ready for ocamlfind and needs a manual
ocamlfind install, after the usual make and make install commands, find a
META for it on the Internet or write one if you want to.
Then install the package with the command
		 ocamlfind META file1 file2 file3 ... filen
where the files(1...n) are those marked in the Makefile

Cheers
Ernesto

#883 From: Martin Jambon <m.jambon@...>
Date: Mon Mar 10, 2003 3:06 pm
Subject: Re: "ocaml_beginners"::[] My first CGI program
m.jambon@...
Send Email Send Email
 
On Mon, 10 Mar 2003, Johann Spies wrote:

> On Fri, Mar 07, 2003 at 03:43:46PM +0100, Martin Jambon wrote:
>
> > [after installing the OCamlNet library]
> ...
>
> > Hope this helps,
>
> Thanks Martin.  It does help indeed!
>
> I would like to confirm my understanding of something (which is not
> strictly ocaml, but rather html):  Am I correct in assuming that the
> datatype multipart/form-data creates a stream if the field is of the
> type "file"?  So when I want to upload a file then ocaml has to read
> the stream and create a file (or files) locally?

You don't need to know how it works if you use the Ocamlnet library.
(anyway I don't know)
The name of the argument of type "file" will simply be associated with the
contents of the uploaded file.

If the file contains "hello\n", and the name of the CGI argument is
the_file_i_need, then Cgi.parse_args will return this:

    [...; ("the_file_i_need", "hello!\n"); ...]

But I don't know how to make the difference between no file and an empty
file.


Martin

#884 From: francois bereux <francois.bereux@...>
Date: Tue Mar 11, 2003 3:30 pm
Subject: Problem using Bigarray with camlidl
francois.bereux@...
Send Email Send Email
 
Hello,

I have a toy example that does not compile; I would like to interface a 1D
Bigarray of integers with C code, using
camlidl.
Here is my attempt :

----- code.c ------
void linear( int* m, int* ia )
{
    int i;
    for( i=0; i< *m; i++ ) { ia[i] = i; }
}

----- bug.idl -----
void toto( [in,ref] int* m, [in,out,length_is(*m),bigarray] int ia[] );


----- test.ml -----
open Bigarray;;
open Bug;;

let lin n =
    let ia = Array1.create int32 n c_layout in
       begin linear ia; ia; end;;

------ Makefile ------
SOURCES = code.c bug.idl test.ml
LIBS = bigarray
RESULT = essai

-include $(OCAMLMAKEFILE)

----------------------------------------------------------
When I compile, I get the following error :
File "test.ml" line 7, character 12-14
This expression has type
    (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array1.t
but is here used with type
    (int, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array1.t

As far as I understand, the kind of the array in the stub code generated by
camlidl is (int,int32_elt) kind, whereas
the int32 in my test.ml file defines a (int32, int32_elt) kind. Am I correct ?
And how can I modify my code so that it
works ? ( I do not know how to define by myself an Array1 with (int, int32_elt)
kind.
If I use floats in the code, this works fine.

Any help would be appreciated,

Sincerely yours,

F. Béreux


[Non-text portions of this message have been removed]

#885 From: francois bereux <francois.bereux@...>
Date: Tue Mar 11, 2003 3:47 pm
Subject: Re: "ocaml_beginners"::[] Problem using Bigarray with camlidl
francois.bereux@...
Send Email Send Email
 
Sorry, there is a typo : read instead
----- bug.idl -----
void linear( [in,ref] int* m, [in,out,length_is(*m),bigarray] int ia[] );

#886 From: Stalkern 2 <stalkern2@...>
Date: Tue Mar 11, 2003 9:34 pm
Subject: Re: "ocaml_beginners"::[] "let _" construct
stalkern2
Send Email Send Email
 
Il  Friday 07 March 2003 15:41, Remi Vanicat ha scritto:
> There is no good reason. It must better to do
>
> let a b = something in
>     .... ;
>     ....
>
> Well. There might be some warning, but you should not discard them by
> using let _, but by using the ignore function.

Furthermore, one can get used to
	 let ... in
constructs because they force the evaluation order, making it exactly like you
write.
By the way, brackets also force the evaluation order. In this list plenty of
reported problems could be solved with either let ... in constructs, or
brackets.

Bye
Ernesto

#887 From: james woodyatt <jhw@...>
Date: Thu Mar 13, 2003 12:03 am
Subject: monads for dummies
dr_strychnine
Send Email Send Email
 
[followups redirected to ocaml_beginners@yahoogroups.com]

On Tuesday, Mar 11, 2003, at 11:47 US/Pacific, mgushee@...
wrote:
>
> [...] My other big problem with Haskell was ... you guessed it:
> monads! I
> must have read every introduction to monads that's available on line
> (and there are at least half a dozen), but I still don't really
> understand them. [...]

I'm a self-taught "programmer" with no formal education in mathematics
or computer science, and I found the monad concept to be fairly
difficult to learn.  It took a leap of consciousness that feels about
the same level of difficulty as what I remember needing to get through
my high school calculus class.

I've been seeing a lot of attempts to explain the theory lately, but
most of them remind me of the kind of thing that I found more confusing
than helpful when I was trying to get my head around the practical
matters.  What I really wanted is a Monads For Dummies tutorial.

Here's what I remember being the crucial tip that got me over the hump:
if you are working with immutable data structures (and there are at
least three in the Ocaml standard library: Map, Set and List), then the
monadic programming style can be really useful for composing
complicated functions for manipulating the contents of those data
structures from assemblies of simpler functions.

Without the monadic programming style, you end up concocting huge
specialized functions for passing into the higher-order standard
library functions, e.g. fold, map, filter, etc., and achieving any kind
of modularity requires careful design work.  The problem can quickly
become hard enough that learning monadic programming starts to seem
like a decent trade.

Once you start using immutable data structures in complex ways (e.g.
doing lots of weird transformations on 'a list values), you may find
that writing your functions as monads will help you modularize your
program, allowing you to encapsulate and reuse computations that would
otherwise be duplicated in scattered fragments of code all over the
place.  (Alternatively, you may want to use mutable data structures
instead, which is always a popular way out of this problem.)

If you discover your immutable data structure manipulations are getting
out of hand, and you want to reorganize your code for better
encapsulation and reusability-- without changing them to use mutable
data structures instead-- then I recommend learning about the
continuation monad first.

Here is the signature of a module I use for the continuation monad in
Ocaml:

    type ('x, 'a) t = ('a -> 'x) -> 'x

    (* let ( >>= ) m f x = m (fun a -> f a x) *)
    val ( >>= ): ('x, 'a) t -> ('a -> ('x, 'b) t) -> ('x, 'b) t

    val return: 'a -> ('x, 'a) t          (* let return x f = f x
       *)
    val lift: 'x -> ('x, 'a) t            (* let lift x _ = x
       *)
    val cont: ('x -> 'x) -> ('x, unit) t  (* let cont f g = f (g ())
       *)
    val eval: ('x, unit) t -> 'x -> 'x    (* let eval m x = m (fun () ->
x)    *)

By using this module, I can make new continuations (functions of type
'x -> 'x) by composing appropriate instances of the continuation monad
type and binding them with functions that chain the results of previous
computations into the subsequent computations.

For a very simple example: if you have a bunch of continuation
functions, e.g. f1, f2, f3 each of type 'x -> 'x, then you can compose
them in sequence like so:

	 let m: ('x, unit) t =
	   cont f1 >>= fun _ ->
	   cont f2 >>= fun _ ->
	   cont f3

In fact, it might be easier to represent f1, f2 and f3 as their monads
to begin with:

	 let m1: ('x, unit) t = cont f1
	 let m2: ('x, unit) t = cont f2
	 let m2: ('x, unit) t = cont f3

	 let m: ('x, unit) t =
	   m1 >>= fun _ ->
	   m2 >>= fun _ ->
	   m3

This defines a new instance of the continuation monad type, but it
isn't exactly the composed continuation function yet.  You *evaluate*
the monad to get the continuation it represents:

	 let f: 'x -> 'x = eval m

The 'return' function is also sometimes called the 'unit' function (but
'unit' is a reserved word in Ocaml, so I like to avoid it).  It
constructs a monad that passes a value through the ( >>= ) operator to
the function that constructs a new monad value with it.  It's good for
use in monad functions that take input from "outside" the encapsulation
and pass it along to other monads.

The 'lift' function is a variant of the 'cont' function which ignores
the 'x value that is input from any previous computation and produces
the 'lifted' value as output.  It's good for use in monad functions
that initialize (or reinitialize) the encapsulated value of the monad.
I probably should have named it 'init' instead.

If I were writing a book on using monads for dummies, I'd launch here
into a series of useful examples showing how to use monads to simplify
very complicated list manipulation functions.  The example above is too
simple to show the power of monadic programming adequately.  I don't
have the time, but it's certainly something that needs to be done.

The continuation monad is only the beginning.  There are several
fundamental types of monad, and it's possible to combine them into
composites to support more operations, e.g. state manipulation,
exception handling, backtracking, etc.  Once you understand how to use
monads in a systematic design, you can take better advantage of the
support for pure functional programming available in the Ocaml language.

In lieu of my writing a long list of examples, here is a paper that I
found immensely helpful in the learning process:

	 <http://www.math.chalmers.se/~augustss/AFP/monads.html>

The examples are written in Haskell, but I found them pretty easy to
translate in my head to the equivalent Ocaml.

Warning: you don't have to go down this path very far before you will
begin to chafe at the "operator overloading" problem.  You can't define
a ( >>= ) operator that will be good for all monad types.  I don't know
how to explain exactly why.  You just can't.  Some folks have proposed
that "extensional polymorphism" would be very helpful  in helping solve
the problem.  I buy that.

Warning2: since Ocaml strictly evaluates all the arguments to a
function before executing it (unless the argument is of type 'a
Lazy.t), you really can't define a proper ( >> ) operator for your
monads.  It won't work the same as the one in Haskell, because Ocaml
evaluates the right operand before it's needed, and you don't buy
anything by fixing it so that it takes a Lazy.t value instead.

If what I've written isn't very helpful to you, then please tell me so
I know not to try to explain this stuff to people.  On the other hand,
if it *is* helpful, that would be nice to know too.


--
j h woodyatt <jhw@...>
that's my village calling... no doubt, they want their idiot back.

#888 From: Warren Harris <wh232@...>
Date: Thu Mar 13, 2003 5:59 pm
Subject: Re: "ocaml_beginners"::[] Digest Number 218
warrensomebody
Send Email Send Email
 
Hi James,

Thanks for taking the time to write this introduction to monads. I think
it's very helpful. I was attracted to ocaml because it's was a
well-designed language, and beautifully implemented system. But
functional programming seems like an academic exercise for the most
part, and monads a tool for reasoning about programs in the absence of
imperative constructs. Could you take a few minutes to explain why I
might _want_ to program in a functional/monadic style instead of with
good old assignment statements?

>Without the monadic programming style, you end up concocting huge
>specialized functions for passing into the higher-order standard
>library functions, e.g. fold, map, filter, etc., and achieving any kind
>of modularity requires careful design work.  The problem can quickly
>become hard enough that learning monadic programming starts to seem
>like a decent trade.
>
>Once you start using immutable data structures in complex ways (e.g.
>doing lots of weird transformations on 'a list values), you may find
>that writing your functions as monads will help you modularize your
>program, allowing you to encapsulate and reuse computations that would
>otherwise be duplicated in scattered fragments of code all over the
>place.  (Alternatively, you may want to use mutable data structures
>instead, which is always a popular way out of this problem.)
>
I'd be particularly interested in seeing an example of what you're
referring to here. I understand HOP, but don't see how monadic style
lends itself to increased modularity.

Finally, is there a relationship between monads in general and
continuation passing style (CPS)? CPS makes control explicit. Are monads
about making state explicit, i.e. transforming state variables into
continuation parameters?

Thanks,

Warren

#889 From: Brian Hurt <brian.hurt@...>
Date: Thu Mar 13, 2003 8:02 pm
Subject: Re: "ocaml_beginners"::[] Digest Number 218
brian.hurt@...
Send Email Send Email
 
On Thu, 13 Mar 2003, Warren Harris wrote:

> Could you take a few minutes to explain why I
> might _want_ to program in a functional/monadic style instead of with
> good old assignment statements?

This question wasn't addressed to me, but I'll answer it anyways.  The
benefits of functional programming all grow out of a common advantage:
that it is easier to reason about functional programs.  Why is this an
advantage?

1) Correctness.  The compiler can ensure that large numbers of 'stupid'
bugs simply don't happen.  While it's not true that the compiler cannot
find all bugs (and thus simply because it compiles doesn't mean it's
correct), my experience is that the compiler finds a surprising number of
them.  From experience, by the time your average Ocaml program *compiles*
cleanly, it has reached a state of correctness that is almost never
reached with C++ programs, and rarely reached with Java programs.

2) Maintainability.  If it's easier for the computer to reason about the
code, it's easier for the programmer to reason about the code.  What
effects a given change would cause is much easier for a programmer to
foresee.  Note that it is still possible to write unmaintainable Ocaml,
but it's a heck of a lot harder.

3) Performance.  Yes, Ocaml only claims to be 'slightly slower than C' (my
experience has been that it's a wash- Ocaml is as fast as C).  This is
primarily because they haven't spent the time and effort to claim those
last few percentage points *yet*.  But all compiler optimizations require
reasoning about the code.  Optimizations are just code transforms, from
less efficient code to more efficient code.  Before the compiler (or the
virtual machine or the CPU, for that matter) can apply the transform they
have to answer several questions- does the transform change the behavior
of the program?  Does it help- is the new form really more efficient?
Etc.

This means that it is very easy for functional compilers to reach 'almost
as fast as C' with very little effort (I seem to recall someone saying
that Ocaml doesn't do much in the way of optimization).  Vr.s C compilers
with literally man-centuries of effort in implementing their optimizers.
So there's a lot of room left to increase the speed of functional
languages compared to C.  And as parallelism becomes more important, I
think there are exploitable opportunities in functional languages that
don't exist in imperitive languages.  Because functional programs don't
depend quite so strictly on order of computation, there's a lot more
ability to be computing two results simultaneously.  This is usefull both
for 'small scale parallelism' (ILP on OOO-super scalar CPUs, and VLIW/EPIC
style parallelism) and 'large scale parallelism' (multi-threading to take
advantage of SMP or SMT/Hyperthreading).

4) Productivity.  Different programmers have different level of
productivity.  So comparing the productivity of two different programmers
is comparing apples to oranges.  But you can compare the productivity of a
given programmer with different languages.  After only a few weeks of
experience with Ocaml (nights and weekends), I figured I was close to
being as productive (in terms of functionality per unit of time) in Ocaml
as I was in C (a language I litterally have decades of experience in).
Yes, in the time it took me to write and debug 100 lines of Ocaml, I could
write and debug 500-1000 lines of C.  But the 100 lines of Ocaml had the
same functionality of the C.

In the long run, Frederick Brooks noted over 20 years ago that the average
number of lines of working code produced by a program was constant, no
matter what the language was (ignoring cut&paste).  The difference was in
the functionality per line of code.  Assembly language had low
functionality per line of code, and thus low functionality produced per
time unit.  Fortran had a much higer functionality per line of code, and
thus higher productivity.

Note that the simplistic application of this lead to monstrosities like
APL, whose sole goal in life was to reduce the number of lines of code.
They missed the forest for the trees.  Most of the time, what a programmer
is doing is reasoning about code- asking himself if the code he just wrote
does what he wants/needs it to do.  And how to make the next bit of code
do what it is needed to do.

But reasoning about the code also allows the compiler to make a lot of
decisions for the programmer.  Big things like memory management and type
inference are obvious, but on 'smaller' things as well.  An example of
what I mean: pattern matching.  Rather than worrying about the exact
most-optimum sequences of if statements to detect various conditions, the
program just lists the various conditions (and what to do if they're
encountered).  The compiler then turns this into a series of if
statements.

Brian

#890 From: oliver@...
Date: Thu Mar 13, 2003 11:33 pm
Subject: changing names => from in_channel to unit ?!
oliver@...
Send Email Send Email
 
Hello,

I have written code for reading in mbox-Mailfiles.

While I had experimented and developed, all went well.

Then I have changed names globally (serach&replace),
and suddenly had different types of the functions
- or at least that is, what I remember what seems
to be happened.

I have looked for the problem, but could not find it.

The first time, when the problem occured I also had
written an mli-file.  But I have removed it then.
And I have restarted the toplevel and tested again.

But it seems, I really have a type-problem and don't know
why (and why suddenly now, after finishing the work).


Well there are two basic functions, which read in the
file and create the output data.
One is called input_header, the other is called
input_body.
Both were called by read_mail (the one, which should
be the only one, which will be put into the
interfecae-definition/signature).

The problem now is, that they are of input-type unit,
instead of input-type in_channel.

So instead of  in_channel -> string list * string list
they have      unit -> string list * string list


I may have overlooked something (I'm pretty shure, that it
has worked correctly (but it's late...)).


Any hint is welcome, and thanks in Advance,
                                        Oliver


Now here comes the Code:


#################################################################
(* Here we have functions to read the mail-header,
    the mail-body, and both together *)

let fl = Stack.create()


let input_header chan =
   let rec read_lines_helper res =
     let sl =
       try
         Some (Stack.pop fl)
       with _ -> begin
                   try
                     Some (read_line chan)
                   with
                     End_of_file -> None  (* no new headers *)
                  end
     in
     match sl with
        None -> List.rev res
      | Some line when String.length line = 0 -> List.rev res (* Header complete
*)
      | Some l -> read_lines_helper (l :: res)  (* prepend new line *)
   in
     read_lines_helper []



let input_body chan =
     let rec read_lines_helper res =
         let sl =
            try
              Some (read_line chan)
            with
              End_of_file -> None  (* EOF *)
         in
     let found_from = fun line -> String.length line >= 5 && String.sub line 0 5
= "From "
     in
         match sl with
            None -> List.rev res           (* ready *)
          | Some line  when (found_from line) -> Stack.push line fl; List.rev res
(* Header complete *)
          | Some l -> read_lines_helper (l :: res)           (* prepend new line
*)
         in
       read_lines_helper []

let print_sl l = List.iter print_endline l

let read_mail chan =
     let head = input_header chan in
     let body = input_body chan   in
   (head, body)


let _ = let ch = open_in "mbox" in
         let h1 = input_header  ch in
         let b1 = input_body    ch in
         let h2 = input_header  ch in
         let b2 = input_body    ch in
         print_sl h1;
         print_sl b1;
         print_sl h2;
         print_sl b2;
         close_in ch

#################################################################

#891 From: Manos Renieris <er@...>
Date: Thu Mar 13, 2003 11:46 pm
Subject: Re: "ocaml_beginners"::[] changing names => from in_channel to unit ?!
er@...
Send Email Send Email
 
On Fri, Mar 14, 2003 at 12:33:24AM +0100, oliver@... wrote:
> Hello,
>
> Well there are two basic functions, which read in the
> file and create the output data.
> One is called input_header, the other is called
> input_body.
> The problem now is, that they are of input-type unit,
> instead of input-type in_channel.
>
> So instead of  in_channel -> string list * string list
> they have      unit -> string list * string list
>
> Now here comes the Code:
>
>
> #################################################################
> (* Here we have functions to read the mail-header,
>    the mail-body, and both together *)
>
> let fl = Stack.create()
>
>
> let input_header chan =
>   let rec read_lines_helper res =
>     let sl =
>       try
>         Some (Stack.pop fl)
>       with _ -> begin
>                   try
>                     Some (read_line chan)
                             ^^^^^^^^^

read_line has type: unit -> string
(it doesn't need a channel, it reads from standard input).
The function you need is "input_line".

The compiler knows the type of read_line (unit->string)
from which it infers that chan must be of type unit.

-- Manos

Messages 862 - 891 of 13889   Oldest  |  < Older  |  Newer >  |  Newest
Add to My Yahoo!      XML What's This?

Copyright © 2010 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Guidelines NEW - Help