f



beginning with ML

Yesterday, while performing an Internet search for lightweight
concurrency,
I run into the Alice system, which is an implementation of the ML
language.
I knew nothing about ML, except that a functional language called ML
existed,
however skimming the tutorial I pretty much liked what I saw, so I
want to do
some experiment with ML programming, at least for educational
purposes.
If you have good pointers to resources, references, libraries, etc,
please let me know. I am especially interested in code snippets and
example of idiomatic ML (an ML cookbook or something like that). I
have already discovered that there is a "SICP in ML" resource, which I
am looking at. My first impression if that ML has been heavily
influenced
by Scheme (it looks like it has been designed as a *reaction* to
Scheme)
which I am familiar with, so a reference like "ML for Scheme
programmers"
would be fine for me. Anyway, I do most of my work in Python, so I am
especially interested in understanding how to convert Python idioms in
ML
idioms. To be concrete, I have made up a problem (which is however not
completely made up, since I had to parse files in custom formats many
times in
real life). Suppose I have a data file like the following:

$ cat example.dat
x
1.0
2.0
3.0
y
-0.5
0.5
z
2
3.0

I want to write a script taking this file as input and returning the
averages as output:

Averages:
x = 2.0
y = 0.0
z = 2.5

The script must recognize the identifiers and the numbers (possibly
converting
integers in floats) and give some error message for wrong inputs. An
idiomatic
modern Python solution could be the following:

import re

def show_averages(names_averages):
    print 'Averages:'
    for name, average in names_averages:
        print '%s = %s' % (name, average)

def apply_(consumer, producer):
    for line in producer:
        consumer.send(line)
    return consumer.send('*END*')

def is_valid_identifier(name):
    return re.match('[_a-zA-Z][_\w\d]*', name)

def is_number(line):
    try:
        float(line)
    except TypeError:
        return False
    else:
        return True

def make_parser():
    names = [] # valid identifiers
    sums = {} # identifiers -> sums
    counts = {} # identifiers -> counts
    current_name = None
    while True:
        line = yield
        if line == '*END*':
            # possibly add a check for counts[n] != 0
            yield [(n, sums[n]/counts[n]) for n in names]; return
        elif is_valid_identifier(line):
            current_name = line
            sums[current_name] = 0
            counts[current_name] = 0
            names.append(current_name)
        elif is_number(line):
            assert current_name, 'No valid identifier in the input
data!'
            sums[current_name] += float(line)
            counts[current_name] += 1
        else:
            raise ValueError('Bad line %r' % line)

def test():
    data = '''
    x
    1.0
    2.0
    3.0
    y
    -0.5
    0.5
    z
    2
    3.0
    '''.split()
    parser = make_parser()
    parser.next() # initialize
    show_averages(apply_(parser, data))

if __name__ =='__main__':
    test()

How would you write an idiomatic ML solution?
Thanks in advance to everybody,

      Michele Simionato

P.S. I was not sure if to post here or in comp.lang.ml, but it looks
like
there is very little traffic on comp.lang.ml. Apologies if this the
wrong
newsgroup.

0
11/5/2007 5:36:33 AM
comp.lang.functional 2791 articles. 0 followers. Post Follow

240 Replies
1692 Views

Similar Articles

[PageSpeed] 42

michele.simionato@gmail.com <michele.simionato@gmail.com> wrote:
[...]
> If you have good pointers to [ML] resources, references, libraries,
> etc, please let me know.
[...]

The MLton wiki has several pages on SML programming techniques and
links to some resources (tutorials, books, ...):

  http://mlton.org/StandardML

If you really want to learn how to program in ML, I would strongly
recommend reading a book length treatment on programming in ML.  After
finishing it, you should read articles on programming techniques in ML
and other functional languages.

> I have already discovered that there is a "SICP in ML" resource,
> which I am looking at. My first impression if that ML has been
> heavily influenced by Scheme (it looks like it has been designed as
> a *reaction* to Scheme) which I am familiar with, so a reference
> like "ML for Scheme programmers" would be fine for me.

ML and Scheme were both born around the same time:

  http://www.levenez.com/lang/history.html#03

The similarity is probably more due to roots in lambda calculus.

> Anyway, I do most of my work in Python, so I am especially
> interested in understanding how to convert Python idioms in ML
> idioms. To be concrete, I have made up a problem (which is however
> not completely made up, since I had to parse files in custom formats
> many times in real life). Suppose I have a data file like the
> following:
[...]
> How would you write an idiomatic ML solution?

What follows below is a similar program written in Standard ML using
no libraries beyond the Standard ML Basis library.  It is by no means
the only way or the most elegant way to write such a program in ML.
It compiles with Alice ML as well as almost any SML compiler
(e.g. MLton, SML/NJ, Poly ML, MLKit, ...).

(* A few utilities - I have these in libraries *)

fun fail m = raise Fail m
datatype ('a, 'b) sum = INL of 'a | INR of 'b
fun apply f x = INR (f x) handle e => INL e
fun eval th = apply th ()
fun throw e = raise e
fun either (fA, fB) = fn INL a => fA a | INR b => fB b
fun try (th, fv, fe) = either (fe, fv) (eval th)
fun past ef x = (ef () : unit ; x)
fun after (th, ef) = try (th, past ef, throw o past ef)

fun inputFile filename = let
   val ins = TextIO.openIn filename
in
   after (fn () => TextIO.inputAll ins,
          fn () => TextIO.closeIn ins)
end

(* Averages *)

fun isIdFirst c = #"_" = c orelse Char.isAlpha c
fun isIdRest c = isIdFirst c orelse Char.isDigit c

fun isId t =
    0 < size t
    andalso isIdFirst (String.sub (t, 0))
    andalso CharVector.all isIdRest t

fun averagesFromList ts = let
   fun loop []      = ()
     | loop (t::ts) =
       if isId t then let
             fun printAverage n sum =
                 print (concat [t, " = ", Real.toString (sum / real n), "\n"])

             fun sumLoop n sum =
              fn []    => printAverage n sum
               | t::ts =>
                 case Real.fromString t
                  of NONE   => (printAverage n sum ; loop (t::ts))
                   | SOME r => sumLoop (n+1) (sum + r) ts
          in
             sumLoop 0 0.0 ts
          end
       else fail (concat ["Expected an identifier, but got '", t, "'."])
in
   print "Averages:\n"
 ; loop ts
end

val averagesFromString = averagesFromList o String.tokens Char.isSpace
val averagesFromFile = averagesFromString o inputFile

(* Test *)

val () =
    averagesFromString
       "x\n\
       \1.0\n\
       \2.0\n\
       \3.0\n\
       \y\n\
       \-0.5\n\
       \0.5\n\
       \z\n\
       \2\n\
       \3.0\n"

> P.S. I was not sure if to post here or in comp.lang.ml, but it looks
> like there is very little traffic on comp.lang.ml. Apologies if this
> the wrong newsgroup.

comp.lang.ml is a moderated newsgroup.  It may sometimes take many
days before a message appears there after one has sent it.  The delay
is a highly effective traffic inhibitor and wastes the time of
everyone involved.  People asking questions often end up getting the
answer earlier from some other newsgroup.  Often several people
provide essentially the same answer to a question, because one cannot
see the previously sent answers that are in the moderation queue.

-Vesa Karvonen
0
11/5/2007 10:26:57 AM
On Nov 5, 11:26 am, Vesa Karvonen <vesa.karvo...@cs.helsinki.fi>
wrote:
>
> What follows below is a similar program written in Standard ML using
> no libraries beyond the Standard ML Basis library.  It is by no means
> the only way or the most elegant way to write such a program in ML.
> It compiles with Alice ML as well as almost any SML compiler
> (e.g. MLton, SML/NJ, Poly ML, MLKit, ...).
> <snip>

That's interesting, thanks. It looks like loops are implemented
exactly as in Scheme.
Is there a "format" utility instead of performing string concatenation
by hand? Also,
you are mixing the formatting of the output with the generation of the
result (i.e. the
print statements are in the core routine). Suppose I want to
accumulate the result
before formatting. What's the preferred data structure? An association
list? A hash table?
What if I want to return the result lazily? Is there a "yield" concept
so that I could
return the averages one at the time?

   Michele Simionato

0
11/5/2007 10:57:47 AM
michele.simionato@gmail.com <michele.simionato@gmail.com> wrote:
> Is there a "format" utility instead of performing string concatenation
> by hand?

If you mean something like printf in C, then here is a page that describes
how one can write something like it in SML:

  http://mlton.org/Printf

I have written a slighly more advanced version (providing both printf and
scanf like functionality), but it isn't currently available from any
public repository.

There are also libraries for more general pretty printing.  I (and I think
several other people independently) have ported Philip Wadler's pretty
printing combinators to SML.  Here is the signature of my port:

  http://mlton.org/cgi-bin/viewsvn.cgi/mltonlib/trunk/com/ssh/prettier/unstable/public/prettier.sig?view=auto

I have also implemented a generic (polytypic) programming library that
contains a generic pretty printing function.  Here is the signature of
the pretty printing generic:

  http://mlton.org/cgi-bin/viewsvn.cgi/mltonlib/trunk/com/ssh/generic/unstable/public/value/pretty.sig?view=auto

Both of these libraries are for Standard ML and work with at least MLton
and SML/NJ.  It should be possible to port the libraries (with a few
changes) to Alice ML as well.

> Also, you are mixing the formatting of the output with the generation of
> the result (i.e. the print statements are in the core routine). Suppose
> I want to accumulate the result before formatting. What's the preferred
> data structure? An association list? A hash table?

Well, that depends entirely on your requirements.  The SML/NJ utility
library contains a hash table implementation (and other data structures)
and several SML implementations contain a port of the library.

> What if I want to return the result lazily?

Alice ML has language support for lazy evaluation:

  http://www.ps.uni-sb.de/alice/manual/futures.html#lazy .

In Standard ML you can use thunks (like in Scheme)

  http://mlton.org/Lazy .

There is also my port of SRFI-45 to Standard ML:

  http://mlton.org/cgi-bin/viewsvn.cgi/mltonlib/trunk/com/ssh/extended-basis/unstable/public/lazy/lazy.sig?view=auto

Using those you can implement lazy sequences.

> Is there a "yield" concept so that I could return the averages one at
> the time?

There is no yield construct as such.  However, you can implement such
a construct with threads.  In addition to Alice ML, at least SML/NJ
and MLton provide support for light-weight, user-level threads.
Specifically, SML/NJ provides callcc

  http://www.smlnj.org/doc/SMLofNJ/pages/cont.html

and MLton provides user-level threads

  http://mlton.org/MLtonThread .

You can use either of those to implement coroutines similar to what
you have in Python.  (I once wrote such a thing using MLton's
user-level threads, but I don't seem to have the code anymore.  Maybe
I should write it again someday.)

You can also do coroutine like programming using continuation passing
style.

-Vesa Karvonen
0
11/5/2007 11:49:03 AM
On Nov 5, 12:49 pm, Vesa Karvonen <vesa.karvo...@cs.helsinki.fi>
wrote:
<snip lots of useful info>

I have yet another question. Which implementation would you recommend
for a beginner?
My only constraints are that it should work both on Linux and on Intel
Mac. I would like something
reliable and with good error messages.

 Michele Simionato

0
11/5/2007 2:56:18 PM
michele.simionato@gmail.com <michele.simionato@gmail.com> wrote:
[...]
> I have yet another question. Which implementation would you
> recommend for a beginner?  My only constraints are that it should
> work both on Linux and on Intel Mac. I would like something reliable
> and with good error messages.

Note that Alice ML is an extension of Standard ML.  It provides quite a
few features (e.g. futures, higher-order functors, pickling, packages,
.... see http://www.ps.uni-sb.de/alice/) that are not included in the
definition of Standard ML (only higher-order functors are provided by a
couple of other SML implementations).  So, if you want to play with those
features, then you should go with Alice ML.  I can't comment on the
reliability of the implementation or the quality of the error messages,
because I don't use Alice ML on a daily basis.

Personally, I use mainly MLton and SML/NJ.  Of those two, MLton is, in my
subjective experience, somewhat more reliable (although SML/NJ is also
very reliable) and gives noticeably higher quality error messages, but
this is just my personal experience.  MLton also makes it trivial to
create stand-alone executables with excellent performance.  However, MLton
is a whole-program compiler, compile times can be quite long (from 5
seconds to several minutes depending on program size), and does not
provide an interactive REPL.  SML/NJ provides a REPL, separate
compilation, and compiles quickly.  But there are many more implementation
of Standard ML, see http://mlton.org/StandardMLImplementations .

Then there is also O'Caml, which is very similar to Standard ML, but
different.  Here are a few language comparisons:

  http://www.cs.berkeley.edu/~adamc/mlcomp/
  http://mlton.org/OCaml
  http://www.mpi-sws.mpg.de/~rossberg/sml-vs-ocaml.html

Personally, I programmed for some time (for about a year) in O'Caml
before switching to Standard ML.  O'Caml is a nice language, but
Standard ML is arguably simpler, cleaner, more orthogonal, specified
more rigorously (formally), and has fewer language features.  These
are some of the reasons, in addition to the existence of MLton, why I
personally prefer Standard ML, but people like me are in the minority.
:-)

-Vesa Karvonen
0
11/5/2007 4:04:35 PM
michele.simionato@gmail.com wrote:
> I have already discovered that there is a "SICP in ML" resource, which
> I am looking at. My first impression if that ML has been heavily
> influenced by Scheme (it looks like it has been designed as a
> *reaction* to Scheme) which I am familiar with, so a reference like
> "ML for Scheme programmers" would be fine for me.

The languages have many similarities and have influenced each other
(There's actually a fair amount of ML influence on Scheme).  But, if
all you're looking at is my SICP translation in isolation, then the
parallels between the two is being overemphasized on purpose.
Hopefully the resource provides a quick glance (whets the appetite)
for those that are familiar with SICP or Scheme.  Other resources,
such as those pointed to by Vesa, will help you get a more methodical
introduction to ML.

Chris

0
11/5/2007 9:17:17 PM
michele.simionato@gmail.com wrote:
> I have yet another question. Which implementation would you recommend
> for a beginner?

OCaml if you're running Linux or Mac OS X and F# if you're running Windows.

While SML is a very nice language and well worth learning, its user base is
about 10x smaller than OCaml's and is split across various incompatible
compilers. So SML has fewer libraries and is less practical.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/5/2007 11:34:17 PM
On Nov 5, 6:56 am, "michele.simion...@gmail.com"
<michele.simion...@gmail.com> wrote:
....
> Which implementation would you recommend
> for a beginner?

O'Caml is somewhat different and less clean language that Standard
ML.  I prefer SML and use SML/NJ exclusively because of the support
for Concurrent ML. (Book by Reppy.)

Moscow ML was designed as an implementation for beginners and does not
(or anyway, did not do so correctly) support the module features.
Nonetheless, given the intent of the design, you might wish to start
there.

MLton is a good choice as well, especially given Vesa's plug for the
quality of the error messsages.

I don't know enough about MLKit or Alice to offer you any advice
regarding those compilers's error messages.

SML/NJ has quite a good utility library.  The code ought to compile in
MLton as well.  In particular it offers the ListFormat structure which
is quite convenient assistant in converting list to printable
strings.  The SML Basis Library has a supporting book by Reppy and
Gansner which I recommend having in book form.  In particular, the
String structure offers String.concat and String.concatWith both of
which run faster that ^ when concatenating many strings. (More
convenient, often, as well.)

The best starting textbook, IMO, remains that by L.C. Paulson, "ML for
the working programmer", but if you are familiar with Scheme you may
not need it.

0
dbenson (109)
11/6/2007 12:21:35 AM
On Nov 5, 2:57 am, "michele.simion...@gmail.com"
<michele.simion...@gmail.com> wrote:
> ...
> What's the preferred data structure? An association
> list? A hash table?
> What if I want to return the result lazily? ...
>
>    Michele Simionato

Lists are commonly used, being functional, but hash tables are also
used.  I use the RedBlackTree implemenation in the utility library
extensively for the larger lookup data structures required.

SML/NJ implements more than just SML.  It includes a very fast
implementation of callcc and also supports lazy computation:

http://www.smlnj.org/

Some of these features may also be in Alice ML, I'm not sure.

Also, there ia an on-line book by Robert Harper (Carenige-Mellon) at
his web site.  It is more advanced and theoretical than Paulson's
undergraduate textbook.


0
dbenson (109)
11/6/2007 12:50:42 AM
David B. Benson wrote:
> On Nov 5, 6:56 am, "michele.simion...@gmail.com"
> <michele.simion...@gmail.com> wrote:
>> Which implementation would you recommend for a beginner?
> 
> O'Caml is somewhat different and less clean language that Standard
> ML...

OCaml is also a far more powerful language though. Here's a list of some
really useful features added by OCaml:

.. Pattern guards
.. Or-patterns
.. Lazy stream parsing
.. Macros
.. Polymorphic variants
.. OOP
.. Labelled and optional arguments
.. Private types
.. Ad-hoc polymorphic printing (printf)
.. Array literals
.. Can export infix operator definitions from modules
.. Capitalized type constructors
.. Module hierarchy can be reflected in source directory structure
.. Conventional unary minus
.. Extensive currying in the stdlib
.. Mutable record fields
.. Structural types
.. Recursive types
.. Higher-order functors
.. "open" allowed in signatures
.. Standard integrated build tool
.. Portability of a substantial subset to .NET thanks to F#
.. Lightweight and efficient FFI with auto codegen
.. Lots of documentation
.. More libraries than SML
.. Wider use in industry
.. API browser and IDEs with type throwback
.. High-performance interactive mode
.. Actively developed
.. Polymorphic structural equality, comparison and hashing

SML adds a few features not in OCaml:

.. Equality types
.. Single notion of equality
.. First-class type constructors
.. User defined precedence and associativity of new infix operators
.. Ad-hoc polymorphic arithmetic operations
.. Immutable strings
.. Anonymous record types

The only one I value is equality types but F# has an even better solution to
the same problem.

F# also has a wide variety of features not found in SML and does an
excellent job in carrying the enormous productivity boost of using a
language like OCaml to the .NET platform.

I'm only just learning Scala but my impression is that its design diverged
much too far from core ML and, consequently, it fails to capture the
productivity boost.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 3:27:17 AM
michele.simionato@gmail.com wrote:
> Suppose I have a data file like the following:
> 
> $ cat example.dat
> x
> 1.0
> 2.0
> 3.0
> y
> -0.5
> 0.5
> z
> 2
> 3.0
> 
> I want to write a script taking this file as input and returning the
> averages as output:
> 
> Averages:
> x = 2.0
> y = 0.0
> z = 2.5
> 
> The script must recognize the identifiers and the numbers (possibly
> converting
> integers in floats) and give some error message for wrong inputs.
> ...
> How would you write an idiomatic ML solution?

How about this:

include Map.Make(String);;

let inc k dv m =
  let n, v = try find k m with Not_found -> 0, 0. in
  add k (n + 1, v +. dv) m;;

let read_line line =
  try `Float(float_of_string line) with _ -> `String line;;

let rec read ?(k="") ?(m=empty) ch =
  match try read_line(input_line ch) with End_of_file -> `None with
  | `Float dv -> read ~k ~m:(inc k dv m) ch
  | `String k' -> read ~k:k' ~m ch
  | `None -> m;;

open Printf;;

let () =
  printf "Averages:\n";
  iter (fun k (n, v) -> printf "%s = %f\n" k (v /. float n)) (read stdin);;

Compiling and running "sum.ml":

$ ocamlbuild sum.byte
Finished, 3 targets (0 cached) in 00:00:00.
$ ./sum.byte <data.txt
Averages:
x = 2.000000
y = 0.000000
z = 2.500000

> P.S. I was not sure if to post here or in comp.lang.ml, but it looks
> like
> there is very little traffic on comp.lang.ml. Apologies if this the
> wrong
> newsgroup.

If you decide to learn OCaml, subscribe to the OCaml beginners list. There
is now a large and friendly community of people there who can give you all
the help and advice you need.

HTH.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 4:20:06 AM
"David B. Benson" <dbenson@eecs.wsu.edu> writes:

> On Nov 5, 6:56 am, "michele.simion...@gmail.com"
> <michele.simion...@gmail.com> wrote:
> ...
>> Which implementation would you recommend
>> for a beginner?
>
> Moscow ML was designed as an implementation for beginners and does not
> (or anyway, did not do so correctly) support the module features.
> Nonetheless, given the intent of the design, you might wish to start
> there.

I believe your information about Moscow ML's lack of support of the
module system is outdated.  The Moscow ML's Owners manual states the
following: "The Moscow ML modules language is a superset of the full
Standard ML modules language".

So about the only reason for not using Moscow ML is if your programs
are very time-consuming, since Moscow ML doesn' generate as fast code
as its competitors.

	Torben

0
torbenm610 (36)
11/6/2007 8:14:20 AM
On Nov 6, 4:27 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> OCaml is also a far more powerful language though. Here's a list of some
> really useful features added by OCaml:
>
> . Pattern guards
> . Or-patterns
> . Lazy stream parsing
> . Macros
> . Polymorphic variants
> . OOP
> . Labelled and optional arguments
> . Private types
> . Ad-hoc polymorphic printing (printf)
> . Array literals
> . Can export infix operator definitions from modules
> . Capitalized type constructors
> . Module hierarchy can be reflected in source directory structure
> . Conventional unary minus
> . Extensive currying in the stdlib
> . Mutable record fields
> . Structural types
> . Recursive types
> . Higher-order functors
> . "open" allowed in signatures
> . Standard integrated build tool
> . Portability of a substantial subset to .NET thanks to F#
> . Lightweight and efficient FFI with auto codegen
> . Lots of documentation
> . More libraries than SML
> . Wider use in industry
> . API browser and IDEs with type throwback
> . High-performance interactive mode
> . Actively developed
> . Polymorphic structural equality, comparison and hashing

While I won't argue your overall conclusion, I have to take issue with
that list. Many points apply to given SML implementaions as well. Some
are weird, e.g. "structural types", which certainly aren't exclusive
to OCaml, and arguably even less pervasive there (cf. records).
Suggesting that SML implementations are not "actively developed" and
generally don't have "high-performance interactive modes" sounds like
active FUD to me (note that - unlike OCaml - SML/NJ or Poly/ML even
compile to native code interactively).

> SML adds a few features not in OCaml:
>
> . Equality types
> . Single notion of equality
> . First-class type constructors
> . User defined precedence and associativity of new infix operators
> . Ad-hoc polymorphic arithmetic operations
> . Immutable strings
> . Anonymous record types

I would add quite a few:

- fully specified evaluation order
- uniform numeric types (esp. syntax for infinite precision ints)
- overflow checking for integers (vs. wrap-around word types)
- first-class tuple and record selectors
- datatype replication
- transparent signature ascription
- type ascriptions for polymorphic definitions
- orthogonal design
- fewer syntax gotchas
- formal definition
- machine-verified proof of soundness for complete language
- many implementations, with interesting extensions
- more textbooks

Just to balance your apparent bias...

     - Andreas

0
rossberg (600)
11/6/2007 1:03:47 PM
rossberg@ps.uni-sb.de wrote:
> While I won't argue your overall conclusion, I have to take issue with
> that list. Many points apply to given SML implementaions as well.

Yes.

> Some 
> are weird, e.g. "structural types", which certainly aren't exclusive
> to OCaml, and arguably even less pervasive there (cf. records).

SML has nothing like structurally-subtyped objects and polymorphic variants.

> Suggesting that SML implementations are not "actively developed"

I was referring to the language rather than the implementations. The OCaml
language continues to evolve but SML does not.

> and 
> generally don't have "high-performance interactive modes" sounds like
> active FUD to me (note that - unlike OCaml - SML/NJ or Poly/ML even
> compile to native code interactively).

No: see the natdynlink branch and compare its performance to that of any
interactive SML implementation on a modern machine. OCaml is much, much
faster.

> I would add quite a few:
> ...
> - transparent signature ascription
> - type ascriptions for polymorphic definitions

What do these two mean?

> - many implementations, with interesting extensions

The same is true of CAML, of course.

> - more textbooks

Do you mean English textbooks? There are 18 OCaml books listed here:

  http://caml.inria.fr/about/books.en.html

and they don't list Practical OCaml. How many SML books are there?

> Just to balance your apparent bias...

You are certainly much more familiar with SML than I am. However, your
statement about OCaml not supporting interactive compilation to native code
is incorrect and your implication that SML's many implementations is a good
thing is completely undermined by the fact that none of them have good
support for 64-bit machines.

We have been using 64-bit machines for several years now and the lack of
support for them by all SML implementations is a serious impediment to our
use of SML.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 2:09:08 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
[...]
> We have been using 64-bit machines for several years now and the lack of
> support for them by all SML implementations is a serious impediment to our
> use of SML.

MLton and Poly/ML both support 64-bit machines.  Looking at commits to
the SML/NJ repository, it would seem that SML/NJ will soon support
64-bit machines.

-Vesa Karvonen
0
11/6/2007 2:35:04 PM
Jon Harrop <usenet@jdh30.plus.com> writes:

> rossberg@ps.uni-sb.de wrote:

>> Suggesting that SML implementations are not "actively developed"
>
> I was referring to the language rather than the implementations. The OCaml
> language continues to evolve but SML does not.

Is that a good thing?  I would rather program in a language that
doesn't change under my feet.

That is not to say that developmen is bad, but it should be by
infrequent introductions of standardised versions instead of
bit-by-bit feature bloat.

Some other advantages of SML over OCaml:

 - Equality tests can't loop.

 - Available on more different platforms.

 - Doesn't support OO (yes, I believe this is an advantage).

	Torben
0
torbenm610 (36)
11/6/2007 3:09:06 PM
On Nov 6, 3:09 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
> rossb...@ps.uni-sb.de wrote:
>
> > Some
> > are weird, e.g. "structural types", which certainly aren't exclusive
> > to OCaml, and arguably even less pervasive there (cf. records).
>
> SML has nothing like structurally-subtyped objects and polymorphic variants.

Except that you already have listed these as separate points, so if
you mean those it's a duplicate.

> > Suggesting that SML implementations are not "actively developed"
>
> I was referring to the language rather than the implementations. The OCaml
> language continues to evolve but SML does not.

OK, true. OTOH, I don't much expect any significant further evolution
for either of them. More likely, there will be a new, cleaned up,
incompatible language at some point.

> > and
> > generally don't have "high-performance interactive modes" sounds like
> > active FUD to me (note that - unlike OCaml - SML/NJ or Poly/ML even
> > compile to native code interactively).
>
> No: see the natdynlink branch and compare its performance to that of any
> interactive SML implementation on a modern machine. OCaml is much, much
> faster.

So you are talking about an experimental branch in the repository? And
does it really modify the standard toplevel to use native compilation
on input?

> > - transparent signature ascription
> > - type ascriptions for polymorphic definitions
>
> What do these two mean?

The first is SML's ":" operator for signatures (as opposed to ":>",
which corresponds to OCaml's ":").

The second refers to the treatment of type variables in annotations.
In SML, when I write, say,

  fun f (x : 'a) = E

then this documents and ensures that f is polymorphic in x. The
respective OCaml,

  let rec f (x : 'a) = E

doesn't mean anything at all. In fact, the compiler happily accepts x
+1 for E.

> > - many implementations, with interesting extensions
>
> The same is true of CAML, of course.

Oh, come on. Not exactly.

> > - more textbooks
>
> Do you mean English textbooks? There are 18 OCaml books listed here:
>
>  http://caml.inria.fr/about/books.en.html

I only count two actual books in English, and one is not even about
OCaml.

> and they don't list Practical OCaml. How many SML books are there?

I believe the major (English) ones are all listed here:

http://mlton.org/StandardMLBooks
http://mlton.org/StandardMLTutorials

> However, your
> statement about OCaml not supporting interactive compilation to native code
> is incorrect

See above.

> and your implication that SML's many implementations is a good
> thing is completely undermined by the fact that none of them have good
> support for 64-bit machines.

I don't know what you count as "good", but at least MLton and Poly/ML
have decent 64 bit support.

- Andreas

0
rossberg (600)
11/6/2007 3:26:19 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
[...]
> OCaml is also a far more powerful language though. Here's a list of some
> really useful features added by OCaml:

A few corrections and comments:

> . Macros

OCaml has CamlP4, which is a PreProcessor and Pretty-Printer.  With
CamlP4 you can implement a parser and pretty-printer for a custom
language.  I wouldn't call CamlP4 a *macro* processor as such.

> . Labelled and optional arguments

The existence of labelled arguments is one of those oblique features
of O'Caml that I abhor.  With support for structural record types
(like in SML) you don't need them.  Optional arguments aren't needed
when you add functional record update (currently not in SML) on top of
structural record types.  There are also ways to write functions with
optional and labelled arguments in SML:
http://mlton.org/OptionalArguments .

> . Ad-hoc polymorphic printing (printf)

This can and has been implemented in SML with a reasonable interface
and better semantics.  See http://mlton.org/Printf for an intro.

> . Array literals

Not necessary, in SML you just write:

  Array.fromList [x1, x2, ..., xN] .

O'Caml also tends to get these things wrong.  Here is an interesting
example of using string literals in O'Caml:

$ ocaml
        Objective Caml version 3.09.2

# let makeAString () = "a" ;;
val makeAString : unit -> string = <fun>
# let aString = makeAString () ;;
val aString : string = "a"
# aString.[0] <- 'b' ;;
- : unit = ()
# aString ;;
- : string = "b"
# let anotherString = makeAString () ;;
val anotherString : string = "b"

> . Can export infix operator definitions from modules

So can Alice ML, for example.  With MLton, one can write libraries
that provide infixed operators.  OCaml has a fixed syntax for infix
operators.  In SML, one can define any symbol as an infix operator
with precedence (0-9) and associativity (left/right).

> . Capitalized type constructors

Taken literally, that statement is simply false.  Proof:

$ ocaml
        Objective Caml version 3.09.2

# type lower_case_type_constructor = unit ;;
type lower_case_type_constructor = unit

> . Module hierarchy can be reflected in source directory structure

You can do that in SML also.  SML, as such, places no restrictions on
where you store your source files.

> . Extensive currying in the stdlib

You call that a feature? ;-)

> . Mutable record fields

Again, this is one of those oblique features of OCaml that I dislike.
In SML, you just use ref cells.

> . Structural types

SML has structural record types.  OCaml has generative record types,
which, I recall, was one of the first gotchas that I encountered when
programming in OCaml.  (OCaml programmers learn how limp, or prefix
their record labels, like in the story of Levine the Genius Tailor:

 http://lambda-the-ultimate.org/node/1014#comment-10571 .)

> . Recursive types

SML has recursive datatypes.  If you are referring to the -rectypes
option, then take your own words for it "you don't want to compile
your code using rectypes":

  http://groups.google.com/group/comp.lang.functional/msg/06538c9672d70841

> . Higher-order functors

Several SML (based) language implementations (e.g. Alice ML, SML/NJ,
Moscow ML) also have higher-order functors.

> . Standard integrated build tool

Some SML implementations also provide build tools.  For example,
SML/NJ provides the "Compilation Manager".

> . Portability of a substantial subset to .NET thanks to F#

SML.NET implements Standard ML for .NET.

> . Lightweight and efficient FFI with auto codegen

Some SML implementations (e.g. MLton, SML/NJ) provide (arguably)
lightweight and efficient FFI's.

> . API browser and IDEs with type throwback

With MLton+Emacs you can also see the inferred types of bindings
(recently developed feature, you need to patch the compiler:
http://mlton.org/pipermail/mlton/2007-November/030038.html) as well as
browse through all uses and the definition of a symbol conveniently:
http://mlton.org/EmacsDefUseMode .

> . Actively developed

In the past week or so I've written patches for 3 different (4 if you
count patches I haven't yet submitted) SML compilers and/or their
Basis library implementations and they have all been committed.

> . Polymorphic structural equality, comparison and hashing

You can implement generic versions of those in SML:

  http://mlton.org/cgi-bin/viewsvn.cgi/mltonlib/trunk/com/ssh/generic/unstable/README?view=markup

Note also that OCaml has actually two polymorphic equality predicates
neither of which works properly for all types.  Not to mention that
many of OCaml's polymorphich operations loop when given cyclic data
structures.  First enter the following lines to the OCaml REPL:

  type trouble = {mutable die : trouble} ;;
  let rec trouble = { die = trouble } ;;

Then enter either one of the following lines:

  trouble = trouble ;;
  trouble < trouble ;;

Don't bother waiting for the evaluation to finish - it won't.

-Vesa Karvonen
0
11/6/2007 4:07:55 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
> [...]
>> We have been using 64-bit machines for several years now and the lack of
>> support for them by all SML implementations is a serious impediment to
>> our use of SML.
> 
> MLton and Poly/ML both support 64-bit machines.

I was very disappointed with the 64-bit MLton. OCaml gives huge performance
on a wide variety of programs when moving to 64-bit. In contrast, MLton has
ranged from slower to only marginally faster. So MLton gives the worst of
both worlds with slow compile times and slow run times...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 4:41:09 PM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> I was referring to the language rather than the implementations. The
>> OCaml language continues to evolve but SML does not.
> 
> Is that a good thing?

From my point of view, yes. In F#, for example, I tend to agree with Don's
evolution of the language and I am even willing to rewrite the code to our
commercial products (well over 250kLOC now) when he makes changes.

OCaml is evolving much more slowly than F#. In fact, I wish OCaml were
developing faster but it is very nice to have a new integrated build system
and revamped macro system this year.

> I would rather program in a language that doesn't change under my feet.

I'm quite surprised by that. I'd have thought industry would be the ones
deterred by language evolution.

> That is not to say that developmen is bad, but it should be by
> infrequent introductions of standardised versions instead of
> bit-by-bit feature bloat.

I think "standardization" is a red herring and was effectively the downfall
of SML. Assuming they wanted SML to gain traction, they should have spent
less time on formal semantics and more time on practical issues like a
consistent build system, FFI and libraries.

> Some other advantages of SML over OCaml:
> 
>  - Equality tests can't loop.

Conversely, OCaml allows recursive values and, in practice, hanging equality
is not a problem and recursive values are useful.

>  - Available on more different platforms.

Are you sure?

>  - Doesn't support OO (yes, I believe this is an advantage).

F# gets OO+FP right, IMHO.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 5:20:17 PM
In article <13ivoa872du71b9@corp.supernews.com>,
Jon Harrop  <usenet@jdh30.plus.com> wrote:
> I'm only just learning Scala but my impression is that its design diverged
> much too far from core ML and, consequently, it fails to capture the
> productivity boost.

Are you implying that Scala is a derivative of ML? Or that being close
to core ML is a prerequisite for a language to be productive?


Lauri
0
la (473)
11/6/2007 5:49:16 PM
Fairly amusing to see SMLers and OCamlers fighting it out just like
academic purity Schemers vs pragmatic usage Common Lispers.

It seems it doesn't matter which side of the fence you're in --
dynamic, static typing whatever:  people disagree in so many
irrelevant details...

0
namekuseijin (630)
11/6/2007 8:45:32 PM
namekuseijin <namekuseijin@gmail.com> wrote:
[...]
> people disagree in so many irrelevant details...

Which details do you find irrelevant?

-Vesa Karvonen
0
11/6/2007 9:05:01 PM
 rossberg@ps.uni-sb.de wrote:
>> > Suggesting that SML implementations are not "actively developed"
>>
>> I was referring to the language rather than the implementations. The
>> OCaml language continues to evolve but SML does not.
> 
> OK, true. OTOH, I don't much expect any significant further evolution
> for either of them. More likely, there will be a new, cleaned up,
> incompatible language at some point.

I really hope that happens. An incredible language could be born by
combining the merits of modern functional programming languages and I don't
think there would be much trouble agreeing on the good features.

I think there is a good chance the JVM will be extended to improve support
for such a language and I think it would be very interesting to pit a
cross-platform JVM-based FPL against F# on .NET. Sun are just getting their
act together about graphics with JOGL, so I think there is enormous
potential for an interactive technical computing environment with graphical
capabilities similar to Mathematica and, if such a platform existed, it
would be ideal.

>> No: see the natdynlink branch and compare its performance to that of any
>> interactive SML implementation on a modern machine. OCaml is much, much
>> faster.
> 
> So you are talking about an experimental branch in the repository?

Yes.

> And does it really modify the standard toplevel to use native compilation
> on input?

Yes. I have been using it to good effect for several months. It simply
augments OCaml 3.10 with an "ocamlnat" program that provides a native-code
compiled top level. Performance is not significantly different from batch
compiled programs and latency is very low (orders of magnitude faster than
Scala, for example).

Several other people have also adopted the natdynlink branch because the
combination of high-performance and interactivity is ideal for
computationally-intensive on-line data dissection by technical users (e.g.
scientists and engineers). As it facilitates other useful things, like
run-time code generation from macros, I'm hoping it will become the main
branch.

>> > - transparent signature ascription
>> > - type ascriptions for polymorphic definitions
>>
>> What do these two mean?
> 
> The first is SML's ":" operator for signatures (as opposed to ":>",
> which corresponds to OCaml's ":").

I'll look into that, thanks.

> The second refers to the treatment of type variables in annotations.
> In SML, when I write, say,
> 
>   fun f (x : 'a) = E
> 
> then this documents and ensures that f is polymorphic in x. The
> respective OCaml,
> 
>   let rec f (x : 'a) = E
> 
> doesn't mean anything at all. In fact, the compiler happily accepts x
> +1 for E.

That's interesting. F# emits a warning if the annotation is inexact and that
really annoys me because I often want to use:

  'a array

where I don't care what 'a is. I'm just declaring an array type.

>> > - many implementations, with interesting extensions
>>
>> The same is true of CAML, of course.
> 
> Oh, come on. Not exactly.

Well, there's caml-light, MetaOCaml, Fresh OCaml, AtomCaml, JCaml, GCaml,
ECaml, JoCaml, HashCaml, XDuce, CDuce, Coq, F#... I assume you mean that
they share a lot of code?

From my point of view, this begs the question why ML compiler writers can't
collaborate and write not only a decent compiler but also decent
development tools, libraries, bindings and so forth.

Indeed, the uptake of SML would explode if someone wrote a decent tutorial
IDE for it.

>> > - more textbooks
>>
>> Do you mean English textbooks? There are 18 OCaml books listed here:
>>
>>  http://caml.inria.fr/about/books.en.html
> 
> I only count two actual books in English, and one is not even about
> OCaml.

Yes. So you meant English textbooks?

OCaml is popular in France (of course!) and Japan. Also, Germany is one of
the most pioneering countries with respect to uptake of OCaml in industry.
So I expect there are many non-English OCaml texts (there are two in
Japanese, for example).

>> and they don't list Practical OCaml. How many SML books are there?
> 
> I believe the major (English) ones are all listed here:
> 
> http://mlton.org/StandardMLBooks
> http://mlton.org/StandardMLTutorials
> 
>> and your implication that SML's many implementations is a good
>> thing is completely undermined by the fact that none of them have good
>> support for 64-bit machines.
> 
> I don't know what you count as "good", but at least MLton and Poly/ML
> have decent 64 bit support.

Ray tracer:

32-bit    run    compile
ocamlopt: 8.20s  0.43s
mlton:    6.43s  2.99s

64-bit
ocamlopt: 3.97s  0.45s
mlton:    8.81s  9.82s

Almost all languages see a performance improvement moving to 64-bit on
floating-point intensive benchmarks like this. In contrast, MLton is
_slower_ in 64-bit! MLton takes 22x longer to compile and runs over 2.2x
slower than OCaml.

So I would not say that MLton has "decent" 64-bit support.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u
0
usenet116 (1778)
11/6/2007 9:54:32 PM
Lauri Alanko wrote:
> In article <13ivoa872du71b9@corp.supernews.com>,
> Jon Harrop  <usenet@jdh30.plus.com> wrote:
>> I'm only just learning Scala but my impression is that its design
>> diverged much too far from core ML and, consequently, it fails to capture
>> the productivity boost.
> 
> Are you implying that Scala is a derivative of ML? Or that being close
> to core ML is a prerequisite for a language to be productive?

ML is significantly more productive than Scala. I gave several specific
examples on the JVM list recently.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 9:55:49 PM
namekuseijin wrote:
> Fairly amusing to see SMLers and OCamlers fighting it out just like
> academic purity Schemers vs pragmatic usage Common Lispers.
>
> It seems it doesn't matter which side of the fence you're in --
> dynamic, static typing whatever:  people disagree in so many
> irrelevant details...

Well, SML, OCaml and F# are far more similar than different on the scale of
things. I'm sure we all agree that the common ML is a hugely productive
language. We've noted a lot of discrepancies here, which is to be expected,
but many of them are unimportant.

I really hope someone creates a new language that draws upon the current
generation of modern FPLs and combines their merits...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 9:56:54 PM
Vesa Karvonen wrote:
> Which details do you find irrelevant?

For me:

.. Uncommon SML extensions
.. Equality looping
.. Support for obscure platforms like HPPA
.. Single notion of equality in SML
.. Anonymous record types

I do not believe these points are important and, IMHO, several of the plus
points cited for SML are trying to solve problems that don't exist.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 10:07:54 PM
David B. Benson wrote:
> On Nov 6, 7:09 am, torb...@app-2.diku.dk (Torben �gidius Mogensen)
> wrote:
> ...
>>  - Doesn't support OO (yes, I believe this is an advantage).
>>
>>         Torben
> 
> I agree.

Have you tried OCaml, Scala and F#?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 10:21:10 PM
Vesa Karvonen wrote:
>> . Macros
> 
> OCaml has CamlP4, which is a PreProcessor and Pretty-Printer.  With
> CamlP4 you can implement a parser and pretty-printer for a custom
> language.  I wouldn't call CamlP4 a *macro* processor as such.

Why not? Can you elaborate?

>> . Labelled and optional arguments
> 
> The existence of labelled arguments is one of those oblique features
> of O'Caml that I abhor.  With support for structural record types
> (like in SML) you don't need them.  Optional arguments aren't needed
> when you add functional record update (currently not in SML) on top of
> structural record types.  There are also ways to write functions with
> optional and labelled arguments in SML:
> http://mlton.org/OptionalArguments .

If that really works then the boiler plate should be in the stdlibs of as
many SML implementations as possible.

>> . Ad-hoc polymorphic printing (printf)
> 
> This can and has been implemented in SML with a reasonable interface
> and better semantics.  See http://mlton.org/Printf for an intro.

Seriously now, you guys like SML because it is "standardized" but its
support for things like printing, compiling and interfacing is so poor that
these standard library functions (in the literal sense) are relegated to a
Wiki page? That's just crazy talk... :-)

Out of curiosity, what is the equivalent of:

  include Map.Make(String)
  let print_map = iter (printf "%s -> %d\n")

in SML (ignoring boiler-plate)?

>> . Array literals
> 
> Not necessary, in SML you just write:
> 
>   Array.fromList [x1, x2, ..., xN] .

Doesn't work in patterns. Don't have active patterns, so can't add it
yourself. Can't implement active patterns because you don't have macros...

> O'Caml also tends to get these things wrong.  Here is an interesting
> example of using string literals in O'Caml:
> 
> $ ocaml
>         Objective Caml version 3.09.2
> 
> # let makeAString () = "a" ;;
> val makeAString : unit -> string = <fun>
> # let aString = makeAString () ;;
> val aString : string = "a"
> # aString.[0] <- 'b' ;;
> - : unit = ()
> # aString ;;
> - : string = "b"
> # let anotherString = makeAString () ;;
> val anotherString : string = "b"

Yes, string literals are static but array literals are not. A source of
confusion, I agree. Gives me something to fill an appendix with though. ;-)

>> . Can export infix operator definitions from modules
> 
> So can Alice ML, for example.  With MLton, one can write libraries
> that provide infixed operators.  OCaml has a fixed syntax for infix
> operators.  In SML, one can define any symbol as an infix operator
> with precedence (0-9) and associativity (left/right).

Sure. Comparing exotic dialects is a whole other ball park though. If you're
going to look at dialects of fringe languages then you must consider how
mature they are.

Look at the number of Ubuntu compiler installations, for example:

ocaml-nox: 3471
smlnj:      186
mosml:      124
mlton:       55

At least on Ubuntu (which is probably representative) there are more than
twice as many people developing GUI applications in OCaml using the
liblablgtk2-ocaml-dev library than are using all SML compilers combined!

This is why I would consider OCaml, F# and maybe SML for commercial work but
certainly not any SML dialects (fringe-fringe languages, if you like). For
one thing, they are not mature enough to be relied upon. The last time I
tried MLton it kept generating code that just segfaulted. Having said that,
Alice ML seems to have come along in leaps and bounds since I last looked.

So I think it is very important to distinguish between seriously obscure
academic projects and defacto standards like OCaml and F#. This also
applies to your responses to "higher-order functors" and "build system", of
course.

>> . Module hierarchy can be reflected in source directory structure
> 
> You can do that in SML also.

Is it automated?

>> . Structural types
> 
> SML has structural record types.  OCaml has generative record types,
> which, I recall, was one of the first gotchas that I encountered when
> programming in OCaml.  (OCaml programmers learn how limp, or prefix
> their record labels, like in the story of Levine the Genius Tailor:

IMHO, you should either nest in modules or use structural typing (i.e.
objects).

>> . Recursive types
> 
> SML has recursive datatypes.  If you are referring to the -rectypes
> option, then take your own words for it "you don't want to compile
> your code using rectypes":
> 
>   http://groups.google.com/group/comp.lang.functional/msg/06538c9672d70841

My advice to a newbie is not relevant here. For non-newbies, rectypes can be
useful. See the ray tracer, for example.

>> . Portability of a substantial subset to .NET thanks to F#
> 
> SML.NET implements Standard ML for .NET.

Perhaps that is one to watch but I suspect it will not be able to compete
with a Microsoft language (F#).

The JVM is wide open for equivalent work though. We have Scala and ocamljava
but both are a long way from critical mass. I'd love to see a good
implementation of a good ML on the JVM.

>> . Lightweight and efficient FFI with auto codegen
> 
> Some SML implementations (e.g. MLton, SML/NJ) provide (arguably)
> lightweight and efficient FFI's.

Are they compatible?

>> . API browser and IDEs with type throwback
> 
> With MLton+Emacs you can also see the inferred types of bindings
> (recently developed feature, you need to patch the compiler:
> http://mlton.org/pipermail/mlton/2007-November/030038.html) as well as
> browse through all uses and the definition of a symbol conveniently:
> http://mlton.org/EmacsDefUseMode .

Fantastic!

>> . Actively developed
> 
> In the past week or so I've written patches for 3 different (4 if you
> count patches I haven't yet submitted) SML compilers and/or their
> Basis library implementations and they have all been committed.

Sorry: I was referring to the language rather than the implementations.

>> . Polymorphic structural equality, comparison and hashing
> 
> You can implement generic versions of those in SML:
> 
>  
http://mlton.org/cgi-bin/viewsvn.cgi/mltonlib/trunk/com/ssh/generic/unstable/README?view=markup

A good thing but still fringe-fringe.

> Note also that OCaml has actually two polymorphic equality predicates
> neither of which works properly for all types.

In practice, they work well. This was discussed here recently.

> Not to mention that 
> many of OCaml's polymorphich operations loop when given cyclic data
> structures.  First enter the following lines to the OCaml REPL:
> 
>   type trouble = {mutable die : trouble} ;;
>   let rec trouble = { die = trouble } ;;
> 
> Then enter either one of the following lines:
> 
>   trouble = trouble ;;
>   trouble < trouble ;;
> 
> Don't bother waiting for the evaluation to finish - it won't.

Sure, OCaml provides lots of functions that can go into infinite loops. In
practice, that isn't a problem.

As I say, SML solves several problems that are not of practical importance
and a few problems that are of practical importance (e.g. equality types).

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/6/2007 10:23:16 PM
On Nov 6, 7:09 am, torb...@app-2.diku.dk (Torben =C6gidius Mogensen)
wrote:
..=2E.
>  - Doesn't support OO (yes, I believe this is an advantage).
>
>         Torben

I agree.


0
dbenson (109)
11/6/2007 10:23:26 PM
In article <<13j1qo7ndh26n85@corp.supernews.com>>,
Jon Harrop <usenet@jdh30.plus.com> wrote:
> David B. Benson wrote:
>> On Nov 6, 7:09 am, torb...@app-2.diku.dk (Torben �gidius Mogensen)
>> wrote:
>> ...
>>>  - Doesn't support OO (yes, I believe this is an advantage).
>>>
>>>         Torben
>> 
>> I agree.
> 
> Have you tried OCaml, Scala and F#?
> 


-- 
Neel R. Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
11/6/2007 11:13:13 PM
On Nov 6, 10:54 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
> > In SML, when I write, say,
>
> >   fun f (x : 'a) = E
>
> > then this documents and ensures that f is polymorphic in x. The
> > respective OCaml,
>
> >   let rec f (x : 'a) = E
>
> > doesn't mean anything at all. In fact, the compiler happily accepts x
> > +1 for E.
>
> That's interesting. F# emits a warning if the annotation is inexact and that
> really annoys me because I often want to use:
>
>   'a array
>
> where I don't care what 'a is. I'm just declaring an array type.

What's wrong with saying

  (_) array

for that?

> >> > - many implementations, with interesting extensions
>
> >> The same is true of CAML, of course.
>
> > Oh, come on. Not exactly.
>
> Well, there's caml-light, MetaOCaml, Fresh OCaml, AtomCaml, JCaml, GCaml,
> ECaml, JoCaml, HashCaml, XDuce, CDuce, Coq, F#... I assume you mean that
> they share a lot of code?

Most of these are either experimental modifications of the OCaml
system itself, or not OCaml at all. I mean, XDuce, CDuce? Coq??

The only system I could count as an alternative implementation of
OCaml is F#, and that already has /much/ less common ground with it
than any two SML implementations.

> From my point of view, this begs the question why ML compiler writers can't
> collaborate and write not only a decent compiler but also decent
> development tools, libraries, bindings and so forth.

That would indeed be nice, but unfortunately not made easy by the way
funding and crediting works for academia.

OTOH, a bit of competition is good even in research. Otherwise you'd
still do your scientific programming in Fortran.

> Indeed, the uptake of SML would explode if someone wrote a decent tutorial
> IDE for it.

What is a "tutorial" IDE? Something like DrScheme or Helium?

FWIW, for Alice ML (another SML system), we implemented a simple Gtk-
based IDE, with type throwback and an interactive data browser. It is
currently used in the local CS 101 courses. Students certainly like it
better than Emacs, but I strongly doubt that something like it - even
if much more elaborate - would impact SML uptake.

> OCaml is popular in France (of course!) and Japan. Also, Germany is one of
> the most pioneering countries with respect to uptake of OCaml in industry.
> So I expect there are many non-English OCaml texts (there are two in
Japanese, for example).

I am not aware of any German texts on OCaml, but I haven't searched.
OTOH, I know about an upcoming textbook on programming, using SML.

> > I don't know what you count as "good", but at least MLton and Poly/ML
> > have decent 64 bit support.
>
> Ray tracer:
>
> 32-bit    run    compile
> ocamlopt: 8.20s  0.43s
> mlton:    6.43s  2.99s
>
> 64-bit
> ocamlopt: 3.97s  0.45s
> mlton:    8.81s  9.82s

That indeed looks disappointing (although I would be careful with
blindly expecting better performance in 64 bit anyway). Did you
contact the developers about it?

> So I would not say that MLton has "decent" 64-bit support.

Have you tried Poly/ML?

0
rossberg (600)
11/6/2007 11:13:58 PM
Jon Harrop wrote:

> Lauri Alanko wrote:
>> In article <13ivoa872du71b9@corp.supernews.com>,
>> Jon Harrop  <usenet@jdh30.plus.com> wrote:
>>> I'm only just learning Scala but my impression is that its design
>>> diverged much too far from core ML and, consequently, it fails to capture
>>> the productivity boost.
>> 
>> Are you implying that Scala is a derivative of ML? Or that being close
>> to core ML is a prerequisite for a language to be productive?
>
> ML is significantly more productive than Scala. I gave several specific
> examples on the JVM list recently.

Jon,

I think we should agree, that examples don't prove or show anything,
except "in this single case it was so and so". General assertions,
which involve the majority of all possible or practical applications
need to be tested by other methods, e.g. _first_ defining a field of
relevance and then conducting a statistically well founded study of
the whole field.

Regards -- Markus

0
11/7/2007 12:03:50 AM
Jon Harrop <usenet@jdh30.plus.com> writes:

>> SML.NET implements Standard ML for .NET.
>
> Perhaps that is one to watch but I suspect it will not be able to compete
> with a Microsoft language (F#).

You /are/ aware of the fact that the SML.NET developers are Microsoft
employees -- and colleagues of Don Syme, aren't you?
0
find19 (1244)
11/7/2007 3:01:19 AM
 rossberg@ps.uni-sb.de wrote:
>> where I don't care what 'a is. I'm just declaring an array type.
> 
> What's wrong with saying
> 
>   (_) array
> 
> for that?

Well I never knew that... :-)

>> Well, there's caml-light, MetaOCaml, Fresh OCaml, AtomCaml, JCaml, GCaml,
>> ECaml, JoCaml, HashCaml, XDuce, CDuce, Coq, F#... I assume you mean that
>> they share a lot of code?
> 
> Most of these are either experimental modifications of the OCaml
> system itself, or not OCaml at all. I mean, XDuce, CDuce? Coq??

Yes. When people create something like Alice ML, do they really reimplement
the entire thing from scratch?

> The only system I could count as an alternative implementation of
> OCaml is F#, and that already has /much/ less common ground with it
> than any two SML implementations.

The main features that differ between OCaml and F# are objects, polymorphic
variants and labelled and optional arguments. None of those are even in
SML, so I would not say that OCaml and F# have less common ground than two
SML implementations at all. Quite the opposite in fact...

>> From my point of view, this begs the question why ML compiler writers
>> can't collaborate and write not only a decent compiler but also decent
>> development tools, libraries, bindings and so forth.
> 
> That would indeed be nice, but unfortunately not made easy by the way
> funding and crediting works for academia.
> 
> OTOH, a bit of competition is good even in research. Otherwise you'd
> still do your scientific programming in Fortran.

:-)

>> Indeed, the uptake of SML would explode if someone wrote a decent
>> tutorial IDE for it.
> 
> What is a "tutorial" IDE? Something like DrScheme or Helium?

Exactly, yes.

> FWIW, for Alice ML (another SML system), we implemented a simple Gtk-
> based IDE, with type throwback and an interactive data browser. It is
> currently used in the local CS 101 courses. Students certainly like it
> better than Emacs, but I strongly doubt that something like it - even
> if much more elaborate - would impact SML uptake.
> 
>> OCaml is popular in France (of course!) and Japan. Also, Germany is one
>> of the most pioneering countries with respect to uptake of OCaml in
>> industry. So I expect there are many non-English OCaml texts (there are
>> two in
> Japanese, for example).
> 
> I am not aware of any German texts on OCaml, but I haven't searched.
> OTOH, I know about an upcoming textbook on programming, using SML.

Tell me more! :-)

>> > I don't know what you count as "good", but at least MLton and Poly/ML
>> > have decent 64 bit support.
>>
>> Ray tracer:
>>
>> 32-bit    run    compile
>> ocamlopt: 8.20s  0.43s
>> mlton:    6.43s  2.99s
>>
>> 64-bit
>> ocamlopt: 3.97s  0.45s
>> mlton:    8.81s  9.82s
> 
> That indeed looks disappointing (although I would be careful with
> blindly expecting better performance in 64 bit anyway). Did you
> contact the developers about it?

I posted a response on c.l.f to their announcement. Initially, MLton just
kept segfaulting for me but at least it now runs to completion, even if it
is slower.

>> So I would not say that MLton has "decent" 64-bit support.
> 
> Have you tried Poly/ML?

No. I've heard great things about Poly/ML and would like to try it though...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 8:19:25 AM
Neelakantan Krishnaswami wrote:
> In article <<13j1qo7ndh26n85@corp.supernews.com>>,
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> David B. Benson wrote:
>>> On Nov 6, 7:09 am, torb...@app-2.diku.dk (Torben �gidius Mogensen)
>>> wrote:
>>> ...
>>>>  - Doesn't support OO (yes, I believe this is an advantage).
>>>>
>>>>         Torben
>>> 
>>> I agree.
>> 
>> Have you tried OCaml, Scala and F#?
>> 
> 
> 

Is that a "no"? ;-)

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 8:20:36 AM
Matthias Blume wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> Perhaps that is one to watch but I suspect it will not be able to compete
>> with a Microsoft language (F#).
> 
> You /are/ aware of the fact that the SML.NET developers are Microsoft
> employees -- and colleagues of Don Syme, aren't you?

Sure, but it isn't being productized. In fact, I'm not sure it is even being
developed any more (last release was over a year ago now).

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 8:41:19 AM
Markus E L wrote:
> I think we should agree, that examples don't prove or show anything,
> except "in this single case it was so and so". General assertions,
> which involve the majority of all possible or practical applications
> need to be tested by other methods, e.g. _first_ defining a field of
> relevance and then conducting a statistically well founded study of
> the whole field.

I only gave examples to elucidate my points rather than to provide evidence.
For example, Scala does not check for exhaustiveness and redundancy of
pattern matches in general and I gave an example where it fails to detect
an obvious bug. Differences like that make it much more difficult to write
correct code in Scala than in any ML.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 8:43:17 AM
Jon Harrop , dans le message (comp.lang.functional:62206), a �crit :
> The main features that differ between OCaml and F# are objects, polymorphic
> variants and labelled and optional arguments.

Functors are also lacking in F#, if I remember correctly.

-- Alain
0
frisch1 (1)
11/7/2007 10:05:18 AM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Torben �gidius Mogensen wrote:

>> Some other advantages of SML over OCaml:
>> 
>>  - Equality tests can't loop.
>
> Conversely, OCaml allows recursive values and, in practice, hanging equality
> is not a problem and recursive values are useful.

Cyclic values (graphs) are quite possible in SML.  But the standard
equality test doesn't follow pointers (it just compares them for
pointer equality), so if you compare two cyclic graphs, you don't get
an infinite loop.  You can fairly easily program graph isomorphism if
you really want to compare cyclic structures for equality.

>>  - Available on more different platforms.
>
> Are you sure?

Fairly:

MLTon runs on 5 different processors (AMD 64, x86, PA-Risc, PowerPC,
Sparc) and many different OSs (multiple BSD flavours, Linux, Windows
under Cygwin, MacOS X, AIX, HPUX, Solaris).

Moscow ML runs under Windows (native), various Unix/Linux/BSD
flavours, .NET and older versions (still Standard ML) runs on Mac OS
(M68K, PPC) and OS/2.  More platforms possible through recompilation
of sources.  I know that version 1.42 was ported to RISC OS (ARM
processor).

PolyML runs on x86, Sparc and PPC under various BSD/Linux/Unix
platforms (including MacOS X).

TILT runs on Sparc (SunOS) and x86 (Linux)

The ML-kit runs under varous Unix/BSD/Linux flavours.

SML.NET (obviosly) runs on .NET

MLj runs under JVM.

Poplog SML runs on various Linux/BSD/Unix flavours on x86, AMD64,
Alpha, PA-Risc, PPC and Sparc and on Windows/x86.

	Torben
0
torbenm7 (46)
11/7/2007 10:08:12 AM
Jon Harrop wrote:

>  rossberg@ps.uni-sb.de wrote:
>>> where I don't care what 'a is. I'm just declaring an array type.
>> 
>> What's wrong with saying
>> 
>>   (_) array
>> 
>> for that?
>
> Well I never knew that... :-)
>
>>> Well, there's caml-light, MetaOCaml, Fresh OCaml, AtomCaml, JCaml, GCaml,
>>> ECaml, JoCaml, HashCaml, XDuce, CDuce, Coq, F#... I assume you mean that
>>> they share a lot of code?
>> 
>> Most of these are either experimental modifications of the OCaml
>> system itself, or not OCaml at all. I mean, XDuce, CDuce? Coq??
>
> Yes. When people create something like Alice ML, do they really reimplement
> the entire thing from scratch?
>
>> The only system I could count as an alternative implementation of
>> OCaml is F#, and that already has /much/ less common ground with it
>> than any two SML implementations.
>
> The main features that differ between OCaml and F# are objects, polymorphic
> variants and labelled and optional arguments. None of those are even in
> SML, so I would not say that OCaml and F# have less common ground than two
> SML implementations at all. Quite the opposite in fact...
>
>>> From my point of view, this begs the question why ML compiler writers
>>> can't collaborate and write not only a decent compiler but also decent
>>> development tools, libraries, bindings and so forth.
>> 
>> That would indeed be nice, but unfortunately not made easy by the way
>> funding and crediting works for academia.
>> 
>> OTOH, a bit of competition is good even in research. Otherwise you'd
>> still do your scientific programming in Fortran.
>
> :-)
>
>>> Indeed, the uptake of SML would explode if someone wrote a decent
>>> tutorial IDE for it.
>> 
>> What is a "tutorial" IDE? Something like DrScheme or Helium?
>
> Exactly, yes.
>
>> FWIW, for Alice ML (another SML system), we implemented a simple Gtk-
>> based IDE, with type throwback and an interactive data browser. It is
>> currently used in the local CS 101 courses. Students certainly like it
>> better than Emacs, but I strongly doubt that something like it - even
>> if much more elaborate - would impact SML uptake.
>> 
>>> OCaml is popular in France (of course!) and Japan. Also, Germany is one
>>> of the most pioneering countries with respect to uptake of OCaml in
>>> industry. So I expect there are many non-English OCaml texts (there are
>>> two in
>> Japanese, for example).
>> 
>> I am not aware of any German texts on OCaml, but I haven't searched.
>> OTOH, I know about an upcoming textbook on programming, using SML.
>
> Tell me more! :-)
>
>>> > I don't know what you count as "good", but at least MLton and Poly/ML
>>> > have decent 64 bit support.
>>>
>>> Ray tracer:
>>>
>>> 32-bit    run    compile
>>> ocamlopt: 8.20s  0.43s
>>> mlton:    6.43s  2.99s
>>>
>>> 64-bit
>>> ocamlopt: 3.97s  0.45s
>>> mlton:    8.81s  9.82s
>> 
>> That indeed looks disappointing (although I would be careful with
>> blindly expecting better performance in 64 bit anyway). Did you
>> contact the developers about it?
>
> I posted a response on c.l.f to their announcement. Initially, MLton just
> kept segfaulting for me but at least it now runs to completion, even if it
> is slower.
>
>>> So I would not say that MLton has "decent" 64-bit support.
>> 
>> Have you tried Poly/ML?
>
> No. I've heard great things about Poly/ML and would like to try it though...

May I point out that you said "ML has no decent 64-bit support" and
then admit not actually having tried the other major ML implementation
that supports 64-bit? You're often jumping to conclusions early.

Regards -- Markus


0
11/7/2007 10:51:32 AM
Jon Harrop wrote:

>>> ML is significantly more productive than Scala. I gave several
>>> specific examples on the JVM list recently.

> Markus E L wrote:
>> I think we should agree, that examples don't prove or show anything,
>> except "in this single case it was so and so". General assertions,
>> which involve the majority of all possible or practical applications
>> need to be tested by other methods, e.g. _first_ defining a field of
>> relevance and then conducting a statistically well founded study of
>> the whole field.
>
> I only gave examples to elucidate my points rather than to provide evidence.

So we can say there is actually no evidence for your claim, ...

> For example, Scala does not check for exhaustiveness and redundancy of
> pattern matches in general and I gave an example where it fails to detect
> an obvious bug. Differences like that make it much more difficult to write
> correct code in Scala than in any ML.

.... which is largely based on theoretical considerations?

It's perhaps my insignifcant mastery of English as a second language,
but what bothers me in your (largely unfounded) statement is the use
of "significant" and "specific" which (to me) somehow gives the
impression that (a) the difference (in productivity) is large and
obvious and (b) that the examples are somehow a cornerstone in seeing
or proving that. Which you now admit isn't the case.

Scientific method, Jon: We've been in that before. Either be cautious
with your claims (formulating them as hypothesis or a matter of
subjective, personal experience) or provide claims and support in a
scientific form. Perhaps the might also help to avoid controversy (at
least a bit). And it's not as misleading for posteriority.

Regards -- Markus
0
11/7/2007 11:07:49 AM
On Nov 7, 9:19 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> Yes. When people create something like Alice ML, do they really reimplement
> the entire thing from scratch?

Usually yes. AFAICT, all of the following systems have disjoint code
bases (except maybe for parts of the library): SML/NJ, MLton, Moscow
ML, Poly/ML, SML.NET, Alice ML, HaMLet, MLWorks. They often use quite
different implementation techniques, so that there isn't really that
much to share anyway. Only parser and type checker could probably have
been reused in some cases, but these are not much work, given that SML
is a relatively simple language with a precise definition.

> The main features that differ between OCaml and F# are objects, polymorphic
> variants and labelled and optional arguments.

It particularly also lacks 3/4 of the module system (functors, general
type abstraction, full signature subtyping, include).

And you cannot ignore that it also adds enough features to the core
language to make it unlikely that any non-toy program natively written
in F# will remain valid OCaml.

Note that I am not criticising F# for that, merely pointing out that
it is a mostly different language.

> None of those are even in
> SML, so I would not say that OCaml and F# have less common ground than two
> SML implementations at all. Quite the opposite in fact...

I have no idea where you draw that conclusion from. There certainly
are some annoying incompatibilities between SML implementations, but
they are mainly related to the build system, not to the language
itself (and in one or two cases, outdated libraries). All systems
faithfully implement complete SML. I have written large SML programs
that run on as many as 8 different implementations, and it did require
almost no special care in the code. Try that with, say, C compilers. I
freely admit that the Makefile setup was a pain, though.

So, sorry, no, that is not true.

> > I am not aware of any German texts on OCaml, but I haven't searched.
> > OTOH, I know about an upcoming textbook on programming, using SML.
>
> Tell me more! :-)

You wanna read German? :-) Not sure it will be interesting to you
anyway, since it's rather aimed at first year CS students:

http://www.oldenbourg-wissenschaftsverlag.de/olb/de/1.c.1321689.de

> > Have you tried Poly/ML?
>
> No. I've heard great things about Poly/ML and would like to try it though...

So what is keeping you? ;-)

0
rossberg (600)
11/7/2007 11:39:09 AM
On Nov 7, 9:41 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> > You /are/ aware of the fact that the SML.NET developers are Microsoft
> > employees -- and colleagues of Don Syme, aren't you?
>
> Sure, but it isn't being productized. In fact, I'm not sure it is even being
> developed any more (last release was over a year ago now).

They are currently putting quite some work into it. Whether it will
ever be commercially productized I don't know.

- Andreas

0
rossberg (600)
11/7/2007 11:59:52 AM
rossberg@ps.uni-sb.de writes:

> On Nov 7, 9:19 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>>
>> Yes. When people create something like Alice ML, do they really reimplement
>> the entire thing from scratch?
>
> Usually yes. AFAICT, all of the following systems have disjoint code
> bases (except maybe for parts of the library): SML/NJ, MLton, Moscow
> ML, Poly/ML, SML.NET, Alice ML, HaMLet, MLWorks.

Add the ML kit to this list.  And probably Poplog ML too.

> They often use quite different implementation techniques, so that
> there isn't really that much to share anyway. Only parser and type
> checker could probably have been reused in some cases, but these are
> not much work, given that SML is a relatively simple language with a
> precise definition.

If I were to make a new SML compiler, I would probably want to lift
the module system implementation and libraries from some other
project, but apart from that I agree.  Making a non-optimising
compiler for the core language should be only a few weeks work.

	Torben

0
torbenm7 (46)
11/7/2007 12:05:14 PM
Alain Frisch wrote:
> Jon Harrop , dans le message (comp.lang.functional:62206), a �crit :
>> The main features that differ between OCaml and F# are objects,
>> polymorphic variants and labelled and optional arguments.
> 
> Functors are also lacking in F#, if I remember correctly.

True.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 12:38:23 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
> > Jon Harrop <usenet@jdh30.plus.com> wrote:
> > [...]
> >> We have been using 64-bit machines for several years now and the lack of
> >> support for them by all SML implementations is a serious impediment to
> >> our use of SML.

> > MLton and Poly/ML both support 64-bit machines.

> I was very disappointed with the 64-bit MLton.

First you claim that there are no SML implementations that support
64-bit machines.  After being told that there are, you reveal that
you've already tried one of them.  In fact, you've known about both
MLton and Poly/ML supporting 64-bit machines for months and here is
the proof:

  http://groups.google.com/group/comp.lang.functional/msg/896d059f7c823e76
  http://groups.google.com/group/comp.lang.functional/msg/6d1b2c5e6fb74662

Jon, I think that you are a liar.

> OCaml gives huge performance on a wide variety of programs when
> moving to 64-bit. In contrast, MLton has ranged from slower to only
> marginally faster.

There were some (more or less known) performance regressions after the
introduction of 64-bit support, AFAIK, due to increased
parameterization of the runtime and elimination of some compiler
primitives for simplicity.  At least one performance issue has been
identified and fixed (in the SVN) since the last release:

  http://mlton.org/pipermail/mlton/2007-November/030042.html

If you'd like to help, you could try and analyze the programs where
you get lower performance than you expected and perhaps there are
optimizations that could be added to MLton.

Note that just going to 64-bits doesn't necessarily improve
performance.  On a 64-bit target, MLton uses 64-bit pointers, which
can increase memory pressure significantly, causing both more cache
misses and more time spent doing GC.

-Vesa Karvonen
0
11/7/2007 1:10:58 PM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> Torben �gidius Mogensen wrote:
>>> Some other advantages of SML over OCaml:
>>> 
>>>  - Equality tests can't loop.
>>
>> Conversely, OCaml allows recursive values and, in practice, hanging
>> equality is not a problem and recursive values are useful.
> 
> Cyclic values (graphs) are quite possible in SML.

Purely functional?

> But the standard 
> equality test doesn't follow pointers (it just compares them for
> pointer equality), so if you compare two cyclic graphs, you don't get
> an infinite loop. You can fairly easily program graph isomorphism if you
> really want to compare cyclic structures for equality. 

This is certainly one of the largely unimportant discrepancies but one of
the few cases I've encountered this difference is in the implementation of
recursive functions in an interpreter. For example, in the "eval" function:

  | ELetRec(var, arg, body, rest) ->
      let rec vars' = (var, VClosure(arg, vars', body)) :: vars in
      eval vars' rest

In SML, I believe you would introduce a mutable reference and give it a
dummy value, set up the new scope and assign new scope to the dummy value
in order to obtain a cyclic data structure.

This is a minor niggle but the OCaml solution seems more elegant to me.

>>>  - Available on more different platforms.
>>
>> Are you sure?
> 
> Fairly:
> 
> MLTon runs on 5 different processors (AMD 64, x86, PA-Risc, PowerPC,
> Sparc) and many different OSs (multiple BSD flavours, Linux, Windows
> under Cygwin, MacOS X, AIX, HPUX, Solaris).
> 
> Moscow ML runs under Windows (native), various Unix/Linux/BSD
> flavours, .NET and older versions (still Standard ML) runs on Mac OS
> (M68K, PPC) and OS/2.  More platforms possible through recompilation
> of sources.  I know that version 1.42 was ported to RISC OS (ARM
> processor).
> 
> PolyML runs on x86, Sparc and PPC under various BSD/Linux/Unix
> platforms (including MacOS X).
> 
> TILT runs on Sparc (SunOS) and x86 (Linux)
> 
> The ML-kit runs under varous Unix/BSD/Linux flavours.
> 
> SML.NET (obviosly) runs on .NET
> 
> MLj runs under JVM.
> 
> Poplog SML runs on various Linux/BSD/Unix flavours on x86, AMD64,
> Alpha, PA-Risc, PPC and Sparc and on Windows/x86.

OCaml runs on all of those architectures and also MIPS. OCaml runs on all of
those platforms and XBox, native Windows, MinGW Windows, Tru64 and IRIX but
not OS/2. There is an unofficial port to AIX.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 1:17:48 PM
Torben �gidius Mogensen <torbenm@app-3.diku.dk> wrote:
[...]
> MLTon runs on 5 different processors (AMD 64, x86, PA-Risc, PowerPC,
> Sparc) and many different OSs (multiple BSD flavours, Linux, Windows
> under Cygwin, MacOS X, AIX, HPUX, Solaris).

Note that porting MLton to a platform that has a working gcc is not
very difficult due to the C (gcc) backend.  So, the above list is by
no means any sort of limit.  A colleague of mine ported MLton to a few
platforms with, I think it is fair to say, novice level SML
programming experience (though he has extensive *nix and programming
experience in several other languages).

-Vesa Karvonen
0
11/7/2007 1:38:19 PM
 rossberg@ps.uni-sb.de wrote:
> On Nov 7, 9:41 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>>
>> > You /are/ aware of the fact that the SML.NET developers are Microsoft
>> > employees -- and colleagues of Don Syme, aren't you?
>>
>> Sure, but it isn't being productized. In fact, I'm not sure it is even
>> being developed any more (last release was over a year ago now).
> 
> They are currently putting quite some work into it. Whether it will
> ever be commercially productized I don't know.

Hmm, I couldn't sworn I read a post by Nick Benton saying it had been
shelved. I can't find it now though...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 2:14:48 PM
Vesa Karvonen wrote:
> Note that just going to 64-bits doesn't necessarily improve
> performance.  On a 64-bit target, MLton uses 64-bit pointers, which
> can increase memory pressure significantly, causing both more cache
> misses and more time spent doing GC.

That problem would equally afflict OCaml.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 2:38:12 PM
Jon Harrop wrote:
> Here's a list of some really useful features added by OCaml:
> 
> . Pattern guards

Some more practical ones as defacto-standard functionality from the stdlib:

.. Pretty printing (Format module)
.. Regular expressions
.. Hash tables with structural hashing
.. Marshalling (albeit type unsafe)
.. GUI API (LablTk)

> SML adds a few features not in OCaml: 
> 
> . Equality types
> ...

.. Arbitrary-precision integer literals
.. Immutable strings
.. More data structures (IIRC)

Does SML provide regular expressions in its stdlib?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 2:52:01 PM
Jon Harrop wrote:

> Vesa Karvonen wrote:
>> Note that just going to 64-bits doesn't necessarily improve
>> performance.  On a 64-bit target, MLton uses 64-bit pointers, which
>> can increase memory pressure significantly, causing both more cache
>> misses and more time spent doing GC.
>
> That problem would equally afflict OCaml.

I vaguely remember that it does.

Regards -- Markus

0
11/7/2007 3:07:57 PM
 rossberg@ps.uni-sb.de wrote:
> On Nov 7, 9:19 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>> Yes. When people create something like Alice ML, do they really
>> reimplement the entire thing from scratch?
> 
> Usually yes. AFAICT, all of the following systems have disjoint code
> bases (except maybe for parts of the library): SML/NJ, MLton, Moscow
> ML, Poly/ML, SML.NET, Alice ML, HaMLet, MLWorks. They often use quite
> different implementation techniques, so that there isn't really that
> much to share anyway. Only parser and type checker could probably have
> been reused in some cases, but these are not much work, given that SML
> is a relatively simple language with a precise definition.

I must concede that there are more separate SML implementations then.

>> The main features that differ between OCaml and F# are objects,
>> polymorphic variants and labelled and optional arguments.
> 
> It particularly also lacks 3/4 of the module system (functors, general
> type abstraction, full signature subtyping, include).

True. I actually miss sigs and abstract types more than functors...

> And you cannot ignore that it also adds enough features to the core
> language to make it unlikely that any non-toy program natively written
> in F# will remain valid OCaml.

That I'm not so sure about. Almost all of F#'s extensions to CAML are
for .NET interop. If you use .NET interop then of course your program will
be difficult to port to OCaml. However, the intersection of the two
languages is very capable and many practical programs will be quite
portable.

> Note that I am not criticising F# for that, merely pointing out that
> it is a mostly different language.

Sure. Microsoft will certainly want to embrace and extend OCaml. They've
already taken most of the good points (I'd like a lot more support for
structural typing though).

>> None of those are even in
>> SML, so I would not say that OCaml and F# have less common ground than
>> two SML implementations at all. Quite the opposite in fact...
> 
> I have no idea where you draw that conclusion from. There certainly
> are some annoying incompatibilities between SML implementations, but
> they are mainly related to the build system, not to the language
> itself (and in one or two cases, outdated libraries). All systems
> faithfully implement complete SML. I have written large SML programs
> that run on as many as 8 different implementations, and it did require
> almost no special care in the code. Try that with, say, C compilers. I
> freely admit that the Makefile setup was a pain, though.

Absolutely.

> So, sorry, no, that is not true.

We are talking at cross purposes. I think you are saying that SML
implementations like SML/NJ and MLton have a proportionately huge overlap
in the languages they can compile because the vast majority is ordinary
SML.

I was saying that, in absolute terms, the common language between OCaml and
F# is larger than the SML language because it includes features like
or-patterns, guarded patterns, polymorphic structural equality, comparison
and hashing, printf, array literals and patterns, regular expressions and
so on. The differences are also bigger but I was focusing on the
similarities.

>> > I am not aware of any German texts on OCaml, but I haven't searched.
>> > OTOH, I know about an upcoming textbook on programming, using SML.
>>
>> Tell me more! :-)
> 
> You wanna read German? :-) Not sure it will be interesting to you
> anyway, since it's rather aimed at first year CS students:
> 
> http://www.oldenbourg-wissenschaftsverlag.de/olb/de/1.c.1321689.de

Bloody hell that's expensive. ;-)

>> > Have you tried Poly/ML?
>>
>> No. I've heard great things about Poly/ML and would like to try it
>> though...
> 
> So what is keeping you? ;-)

So I just tried PolyML (see new thread). Not good...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 3:21:11 PM
Torben �gidius Mogensen wrote:
> If I were to make a new SML compiler, I would probably want to lift
> the module system implementation and libraries from some other
> project, but apart from that I agree.  Making a non-optimising
> compiler for the core language should be only a few weeks work.

I was really thinking of an optimizing native-code backend being a lot of
work and worth stealing. I assume MLton and SML/NJ have independent
backends. In fact, an interest in this led me to the C-- mailing list some
time ago but the consensus seems to be that it is not going places. The JVM
and .NET are the next best things but they are a long way from being
efficient for functional code. At least for .NET, that might change thanks
to the productization of F# and Sun have hinted at improving the JVM for
more exotic languages in the future.

I really would like to see the brains that created the current generation of
ML variants and implementations collaborate on the implementation of a
newer, practical language that borrows all of the best features currently
available.

MLton and SML/NJ were very impressive on x86 and OCaml is also impressive on
AMD64. So I'm not sure it is worth building upon the JVM or .NET for a
general-purpose language if you can achieve much better performance from a
stand-alone FPL.

Perhaps such a project is unfeasible without industrial intervention...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 3:44:00 PM
On Nov 7, 5:39 am, rossb...@ps.uni-sb.de wrote:
> You wanna read German? :-) Not sure it will be interesting to you
> anyway, since it's rather aimed at first year CS students:
>
> http://www.oldenbourg-wissenschaftsverlag.de/olb/de/1.c.1321689.de

Given my perpetual status as an ML newbie, my affinity for translating
introductory texts and my respect for this particular author...  I
might just have to learn German.  (Spent a couple of weeks there some
25 years ago, but learning how to attain a beer is about as far as I
got).  :-)

Grinding the chapter index through babelfish, I get:

- Bases
- high-level procedures
- lists and stringers
- sorting
- constructor and exceptions
- trees
- set theory
- mathematical procedures
- inductive correctness proofs
- running time of recursive procedures
- static and dynamic semantics
- concrete syntax
- data structures
- memory and variable objects
- stacking machines and translators

Only one that I'm not sure about is the last chapter (Stapelmaschinen
und =DCbersetzer).  What exactly is the subject?

Chris

0
11/7/2007 3:51:15 PM
On Nov 7, 4:51 pm, Chris Rathman <Chris.Rath...@tx.rr.com> wrote:
>
> Grinding the chapter index through babelfish, I get:
>
> - Bases

basics

> - high-level procedures

higher-order procedures

> - lists and stringers

lists and strings

> - sorting
> - constructor and exceptions
> - trees
> - set theory
> - mathematical procedures
> - inductive correctness proofs
> - running time of recursive procedures

time complexity of recursive procedures

> - static and dynamic semantics
> - concrete syntax
> - data structures
> - memory and variable objects

memory and mutable objects

> - stacking machines and translators

stack machines and compilers

;-)

0
rossberg (600)
11/7/2007 4:05:38 PM
Chris Rathman wrote:

> On Nov 7, 5:39 am, rossb...@ps.uni-sb.de wrote:
>> You wanna read German? :-) Not sure it will be interesting to you
>> anyway, since it's rather aimed at first year CS students:
>>
>> http://www.oldenbourg-wissenschaftsverlag.de/olb/de/1.c.1321689.de
>
> Given my perpetual status as an ML newbie, my affinity for translating
> introductory texts and my respect for this particular author...  I
> might just have to learn German.  (Spent a couple of weeks there some
> 25 years ago, but learning how to attain a beer is about as far as I
> got).  :-)
>
> Grinding the chapter index through babelfish, I get:
>
> - Bases

Probably: Basics.

> - high-level procedures
> - lists and stringers
> - sorting
> - constructor and exceptions
> - trees
> - set theory
> - mathematical procedures
> - inductive correctness proofs
> - running time of recursive procedures
> - static and dynamic semantics
> - concrete syntax
> - data structures
> - memory and variable objects
> - stacking machines and translators
>
> Only one that I'm not sure about is the last chapter (Stapelmaschinen
> und �bersetzer).  What exactly is the subject?

Stack machines and compilers, probably.

Regards -- Markus

0
11/7/2007 4:14:38 PM
On Nov 7, 4:21 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> > And you cannot ignore that it also adds enough features to the core
> > language to make it unlikely that any non-toy program natively written
> > in F# will remain valid OCaml.
>
> That I'm not so sure about. Almost all of F#'s extensions to CAML are
> for .NET interop.

Above all, F#'s new lightweight syntax might be a major bummer
(although I kind of like it).

> I was saying that, in absolute terms, the common language between OCaml and
> F# is larger than the SML language because it includes features like
> or-patterns, guarded patterns, polymorphic structural equality, comparison
> and hashing, printf, array literals and patterns, regular expressions and
> so on. The differences are also bigger but I was focusing on the
> similarities.

Frankly, I consider that a dubious measurement, qualitatively as well
as quantitatively.

> >http://www.oldenbourg-wissenschaftsverlag.de/olb/de/1.c.1321689.de
>
> Bloody hell that's expensive. ;-)

You mean, compared to the bargain of a related book directed at
scientists? ;-)

> So I just tried PolyML (see new thread). Not good...

Yeah, that's a disappointment. Hopefully, it will improve.

0
rossberg (600)
11/7/2007 4:20:07 PM
 rossberg@ps.uni-sb.de wrote:
> On Nov 7, 4:21 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
>> > And you cannot ignore that it also adds enough features to the core
>> > language to make it unlikely that any non-toy program natively written
>> > in F# will remain valid OCaml.
>>
>> That I'm not so sure about. Almost all of F#'s extensions to CAML are
>> for .NET interop.
> 
> Above all, F#'s new lightweight syntax might be a major bummer
> (although I kind of like it).

Very true. The problem there is that F#'s development environment is geared
up for #light. Also, there is no way to de#light your code.

>> I was saying that, in absolute terms, the common language between OCaml
>> and F# is larger than the SML language because it includes features like
>> or-patterns, guarded patterns, polymorphic structural equality,
>> comparison and hashing, printf, array literals and patterns, regular
>> expressions and so on. The differences are also bigger but I was focusing
>> on the similarities.
> 
> Frankly, I consider that a dubious measurement, qualitatively as well
> as quantitatively.

Speaking from experience, porting substantial amounts of code between OCaml
and F# is easy going. The only major surprises I've had were library
related.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/7/2007 5:06:00 PM
I replied yesterday, the site claimed the post was successful, but it
never appeared.  Is this common here?

Anyway, regarding so-called objects, instead I use light weight
concurrency and a style called raveling in a paper that Carl Hauser
and I wrote.

I am currently committed to SML/NJ for the support it gives to
Concurrent ML.  Since my applications run adequately fast on a 0.5 GHz
Pentium III, I have no incentive to try anything else just now.

Eventually I hope to write a front-end to SML/NJ which provides some
of the 'successor ML' features, the way Alice ML does.

0
dbenson (109)
11/7/2007 7:20:32 PM
In article <<13j2ts4nrc92kc2@corp.supernews.com>>,
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Neelakantan Krishnaswami wrote:
>> In article <<13j1qo7ndh26n85@corp.supernews.com>>,
>>>> I agree.
>>> 
>>> Have you tried OCaml, Scala and F#?
> 
> Is that a "no"? ;-)

No, it was pushing the wrong key on my newsreader.


To keep this from being a wasted post, here's a trick for when you
program in OCaml and miss views from F# -- it turns out that views are
very easy to implement in plain OCaml.

I'll use a collection as an example. Let's suppose that we want to let
an arbitrary sequence implementation support a nil-and-cons style
pattern matching interface.

Since we're ML programmers, let's start by giving a signature
describing what a nil-and-cons interface is:

  module type SEQUENCE_VIEW =
  sig
    type 'a t

    type ('a, 'b) view = Nil | Cons of 'a * 'b
    val view : 'a t -> ('a, 'a t) view
    val unview : ('a, 'a t) view -> 'a t
    val map : ('b -> 'c) -> ('a, 'b) t -> ('a, 'c) t
  end

Now, if you have a module that implements a sequence, it just needs to
have an implementation of this signature as a submodule. I'll use
join lists as an example:

  module type JOIN_LIST =
  sig
    type 'a jlist
  
    val empty : 'a jlist
    val one   : 'a -> 'a jlist
    val join  : 'a jlist -> 'a jlist -> 'a jlist
  
    module View : SEQUENCE_VIEW with type 'a t = 'a jlist
  end

  module JList : JOIN_LIST = ... 

Now, whenever you use a join list, you can write functions that
iterate over it as if it were a cons list, using the view interface:

  module Test =
  struct
    open JList
    open View
  
    let x = join (one "foo") (one "bar")
    let y = join x x
    let z = join y y 
  
    let rec concat js =
      match map view (view js) with
      | Nil -> ""
      | Cons(s, Nil) -> s
      | Cons(s, rest) -> s ^ ", " ^ (concat (unview rest))
  end

The concat function takes a join list of strings, and returns a
comma-separated string of the elements. Note that we have to do a
nested pattern match here, in order to handle the 1-element case
specially. So this demonstrates we can program with this abstract type
very much like an ordinary datatype. The difference is that the
embeddings and projections are explicit.

Another nice thing about this is that we can use the fact that a view
is a module to write generic map, fold, and unfold functions:

  module HOF(V : SEQUENCE_VIEW) = 
  struct
    open V

    let rec map f seq = 
      match view seq with
      | Nil -> unview Nil
      | Cons(x, rest) -> unview (Cons(f x, map f rest))

    let rec foldr f init seq = 
      match view seq with
      | Nil -> init
      | Cons(x, rest) -> f x (foldr f init)

    let rec unfold f seed = 
      match f seed with
      | Nil -> unview Nil
      | Cons(x, seed') -> unview (Cons(x, unfold f seed'))
  end 

Now any abstract type that supports a sequence view can automatically
get a fold function from it, by instantiating the HOF functor.

If you're curious about the implementation of JList, here it is
below. The implementation of view and unview are pretty much exactly
what you'd write as view functions in F#. 

  module JList : JOIN_LIST =
  struct
    type 'a jlist = Empty | One of 'a | Join of 'a jlist * 'a jlist
  
    let empty = Empty
  
    let one x = One x
  
    let join s1 s2 =
      match s1, s2 with
      | Empty, s
      | s, Empty -> s
      | _ -> Join(s1, s2)
  
    module View =
    struct
      type 'a t = 'a jlist
      type ('a, 'b) viewtype = Nil | Cons of 'a * 'b
  	
      let rec view s =
  	match s with
  	| Empty -> Nil
  	| One x -> Cons(x, Empty)
  	| Join(s, s') ->
  	    (match view s with
  	     | Nil -> assert false
  	     | Cons(x, s'') -> Cons(x, join s'' s'))
  
      let unview s =
  	match s with
  	| Nil -> Empty
  	| Cons(x, xs) -> join (one x) xs
  
      let map f view =
  	match view with
  	| Nil -> Nil
  	| Cons(x, xs) -> Cons(x, f xs)
    end
  end

-- 
Neel Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
11/7/2007 7:38:01 PM
The definition of Standard ML in effect treats strings as in

type string = char vector

but one can easily build a module for mutable strings starting with

type mutable_string = char array

if this is somehow desirable.


0
dbenson (109)
11/7/2007 7:54:21 PM
On Nov 7, 8:38 pm, Neelakantan Krishnaswami <ne...@cs.cmu.edu> wrote:
>
>   module type SEQUENCE_VIEW =
>   sig
>     type 'a t
>
>     type ('a, 'b) view = Nil | Cons of 'a * 'b
>     val view : 'a t -> ('a, 'a t) view
>     val unview : ('a, 'a t) view -> 'a t
>     val map : ('b -> 'c) -> ('a, 'b) t -> ('a, 'c) t
>   end

The problem I commonly have with this approach is that it can be
expensive: it requires constructing a second-level (or nth-level) view
every time you perform a match with nested patterns, regardless of
whether any of the nested cases is actually tried. Assuming that
constructing a view has non-neglectible cost, and assuming you have a
big match where only one or two patterns actually are nested (which is
quite a common case IME), this is a clear disadvantage compared to
"real" views.

- Andreas

0
rossberg (600)
11/7/2007 8:21:46 PM
Neelakantan Krishnaswami wrote:
> In article <<13j2ts4nrc92kc2@corp.supernews.com>>,
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> Neelakantan Krishnaswami wrote:
>>> In article <<13j1qo7ndh26n85@corp.supernews.com>>,
>>>>> I agree.
>>>> 
>>>> Have you tried OCaml, Scala and F#?
>> 
>> Is that a "no"? ;-)
> 
> No, it was pushing the wrong key on my newsreader.

:-)

> To keep this from being a wasted post, here's a trick for when you
> program in OCaml and miss views from F# -- it turns out that views are
> very easy to implement in plain OCaml...

Your OCaml solution is quite correct but far from "very easy". The OCaml is
tedious for two main reasons:

1. Pattern matches that could be flat end up being heavily nested in order
to deconstruct only when necessary.

2. Active patterns of different depths cannot share their action so the
action must be split into a separate function to avoid uncontrolled code
bloat.

Try converting the following function to work on arbitrary sequences, for
example:

  let rec f = function
    | [] -> 0
    | h::1::2::3::t | 3::2::1::h::t -> h + f t
    | _::t -> 1 + f t

In fact, the only thing you need to add to OCaml in order to make it easy to
handle all uses of active patterns that I am aware of is lazy pattern
matching. I proposed on the caml-list that the forcing of lazy values be
integrated into the pattern matcher:

  let force (lazy x) = x

Then your "view" function creates a lazy sequence and you can pattern match
over it directly:

# type 'a seq_aux = Nil | Cons of 'a * 'a seq
  and 'a seq = 'a seq_aux Lazy.t;;

# let rec seq_of_list list =
    lazy
      (match list with
       | [] -> Nil
       | h::t -> Cons(h, seq_of_list t));;
val seq_of_list : 'a list -> 'a seq = <fun>

# let rec f = function
    | lazy Nil -> 0
    | lazy(Cons(h, lazy(Cons(1, lazy(Cons(2, lazy(Cons(3, t))))))))
    | lazy(Cons(3, lazy(Cons(2, lazy(Cons(1, lazy(Cons(h, t)))))))) ->
        h + f t
    | Cons(_, t) -> 1 + f t;;
val f : int seq -> int = <fun>

As Andreas said, this comes with a performance cost. However, I am more than
willing to suffer the performance cost given the enormous expressive power
this adds!

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/8/2007 1:02:24 AM
For whatever reason, in SML

type string = char vector

hence immutable.  Mutable "strings" are provided by

type mutable_string = char array

which is not in the basis library, but which is easy to program
whatever support for such a type that you require.

No, Jon, I only program in SML/NJ these days, due to the excellent
support for concurrent programming, but also the separate compilation
feature.


0
dbenson (109)
11/8/2007 2:40:19 AM
Markus E L wrote:
> May I point out that you said "ML has no decent 64-bit support" and
> then admit not actually having tried the other major ML implementation
> that supports 64-bit? You're often jumping to conclusions early.

The major SML implementations are SML/NJ and MLton. I have now tested PolyML
and it clearly does not have good 64-bit support (see the new
thread "64-bit PolyML").

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/8/2007 9:26:06 AM
Jon Harrop wrote:

> Markus E L wrote:
>> May I point out that you said "ML has no decent 64-bit support" and
>> then admit not actually having tried the other major ML implementation
>> that supports 64-bit? You're often jumping to conclusions early.
>
> The major SML implementations are SML/NJ and MLton. I have now tested PolyML
> and it clearly does not have good 64-bit support (see the new
> thread "64-bit PolyML").

OK. I've answered to that and now think your definition or your method
of benchmarking "good 64-bit support" is flawed. See my reply over
there.

Regards -- Markus


0
11/8/2007 10:35:05 AM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Torben �gidius Mogensen wrote:
>> Jon Harrop <usenet@jdh30.plus.com> writes:
>>> Torben �gidius Mogensen wrote:
>>>> Some other advantages of SML over OCaml:
>>>> 
>>>>  - Equality tests can't loop.
>>>
>>> Conversely, OCaml allows recursive values and, in practice, hanging
>>> equality is not a problem and recursive values are useful.
>> 
>> Cyclic values (graphs) are quite possible in SML.
>
> Purely functional?

Only indirectly by defining recursive closure structures.

> This is certainly one of the largely unimportant discrepancies but one of
> the few cases I've encountered this difference is in the implementation of
> recursive functions in an interpreter. For example, in the "eval" function:
>
>   | ELetRec(var, arg, body, rest) ->
>       let rec vars' = (var, VClosure(arg, vars', body)) :: vars in
>       eval vars' rest
>
> In SML, I believe you would introduce a mutable reference and give it a
> dummy value, set up the new scope and assign new scope to the dummy value
> in order to obtain a cyclic data structure.

Or represent environments as functions.

> This is a minor niggle but the OCaml solution seems more elegant to me.

In a non-lazy language, I would not really call this elegant -- I
would call it risky.

	Torben
0
torbenm7 (46)
11/8/2007 10:40:08 AM
In article <<13j4oifgui7lo94@corp.supernews.com>>,
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Neelakantan Krishnaswami wrote:
> Try converting the following function to work on arbitrary sequences, for
> example:
> 
>   let rec f = function
>     | [] -> 0
>     | h::1::2::3::t 
>     | 3::2::1::h::t -> h + f t
>     | _::t -> 1 + f t

Okay:
  
  let z x = x
  let s  f x = (map f (view x))
  let s' f x = unview (map f x)
  let ( ** ) f x = f x

  
  let rec f list = 
    match (s ** s ** s ** s ** z) list with
    | Nil -> 0
    | Cons(h, Cons(1, Cons(2, Cons(3, t)))) 
    | Cons(3, Cons(2, Cons(1, Cons(h, t)))) -> h + f(t)
    | _ :: t -> 1 + f ((s' ** s' ** s' ** z) t)
 
This is basically the same code, with the exception that you have to
count how many times to inject or project a term from the nesting.
This is more annoying than true views, but it's not that big a deal.

You can see that basically we're writing the number of projections or
embeddings as a unary number. This pattern shows fairly commonly when
you start building HOF combinator libraries. I should have put the
first four lines into a utility functor yesterday, but Usenet is not
production code. :)

> In fact, the only thing you need to add to OCaml in order to make it
> easy to handle all uses of active patterns that I am aware of is
> lazy pattern matching. I proposed on the caml-list that the forcing
> of lazy values be integrated into the pattern matcher.

Yes, I agree with this. That would eliminate most of the performance
penalty.

I'm not opposed to adding syntactic sugar for views, though. I just
want them specified in such a way that they will integrate nicely with
the module system.


-- 
Neel R. Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
11/8/2007 6:18:14 PM
Neelakantan Krishnaswami wrote:
>   let z x = x
>   let s  f x = (map f (view x))
>   let s' f x = unview (map f x)
>   let ( ** ) f x = f x
> 
>   
>   let rec f list =
>     match (s ** s ** s ** s ** z) list with
>     | Nil -> 0
>     | Cons(h, Cons(1, Cons(2, Cons(3, t))))
>     | Cons(3, Cons(2, Cons(1, Cons(h, t)))) -> h + f(t)
>     | _ :: t -> 1 + f ((s' ** s' ** s' ** z) t)
>  
> This is basically the same code, with the exception that you have to
> count how many times to inject or project a term from the nesting.
> This is more annoying than true views, but it's not that big a deal.

Unless I've misunderstood, that is a very big deal because you're doing
asymptotically more work. The whole point is to deconstruct lazily but I
believe your hoisted "(s ** s ** s ** s ** z) list" will eagerly
deconstruct the next four elements and the last clause simply discards that
result. So you've replaced T(n) with T(4 n) or, in general, T(n) with T(k
n) where "k" is the depth of the deepest pattern. This is exactly what I
was trying to avoid.

> I'm not opposed to adding syntactic sugar for views, though. I just
> want them specified in such a way that they will integrate nicely with
> the module system.

I think the F# solution is orthogonal to the module system (not that F# has
a module system...).

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/8/2007 7:32:55 PM
Markus E L wrote:
> Scientific method, Jon: We've been in that before. Either be cautious
> with your claims (formulating them as hypothesis or a matter of
> subjective, personal experience) or provide claims and support in a
> scientific form. Perhaps the might also help to avoid controversy (at
> least a bit). And it's not as misleading for posteriority.

Anyone with any significant experience of any ML or Haskell will be able to
understand the statements that I made.

The difference is quite simple: just look at the pattern matching
capabilities of Scala compared to SML/OCaml/Haskell/F#.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/10/2007 2:08:22 AM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> In SML, I believe you would introduce a mutable reference and give it a
>> dummy value, set up the new scope and assign new scope to the dummy value
>> in order to obtain a cyclic data structure.
> 
> Or represent environments as functions.

Interesting.

>> This is a minor niggle but the OCaml solution seems more elegant to me.
> 
> In a non-lazy language, I would not really call this elegant -- I
> would call it risky.

If it doesn't cause problems in practice (e.g. in OCaml code), is it fair to
call it "risky"?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/10/2007 2:10:01 AM
Jon Harrop <usenet@jdh30.plus.com> wrote:
[...]
> I was very disappointed with the 64-bit MLton. OCaml gives huge performance
> on a wide variety of programs when moving to 64-bit. In contrast, MLton has
> ranged from slower to only marginally faster. So MLton gives the worst of
> both worlds with slow compile times and slow run times...

So, you are saying that 64-bit MLton is sometimes faster than OCaml
and that gives you slow run times.  So, what you are really sayins is
that OCaml is not competitive.

-Vesa Karvonen
0
11/11/2007 7:01:33 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
> [...]
>> I was very disappointed with the 64-bit MLton. OCaml gives huge
>> performance on a wide variety of programs when moving to 64-bit. In
>> contrast, MLton has ranged from slower to only marginally faster. So
>> MLton gives the worst of both worlds with slow compile times and slow run
>> times...
> 
> So, you are saying that 64-bit MLton is sometimes faster than OCaml
> and that gives you slow run times.  So, what you are really sayins is
> that OCaml is not competitive.

64-bit MLton ranges from slower to marginally faster than 32-bit MLton.
Nothing to do with OCaml.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 7:20:53 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
> > Which details do you find irrelevant?

> For me:

> . Uncommon SML extensions

There are a few extensions that are common to a few SML compilers.
For example, both SML/NJ and MLton provide an implementation of
ML-NLFFI, an advanced foreign function interface for calling C from
SML.

> . Support for obscure platforms like HPPA

Maybe not you, but I know, for a fact, that support for such obscure
platforms is important to some companies.

> . Single notion of equality in SML
> . Equality looping

I don't find this irrelevant and I even some O'Caml programmers don't
find it irrelevant.  For example, a part of a recent ML workshop
article, Practical Generic Programming in OCaml, is an implementation
of SML style equality, which really is needed.

> . Anonymous record types

I find anonymous record types extremely convenient (in comparison to
generative record types).  Comparing the convenience of structural and
generative record types is very much like comparing polymorphic
variants and ordinary variants.

> I do not believe these points are important and, IMHO, several of the plus
> points cited for SML are trying to solve problems that don't exist.

Perhaps the case is just that you don't personally see the importance
of the problems being solved.

-Vesa Karvonen
0
11/11/2007 7:23:58 PM
Torben �gidius Mogensen <torbenm@app-3.diku.dk> wrote:
[...]
> > This is certainly one of the largely unimportant discrepancies but one of
> > the few cases I've encountered this difference is in the implementation of
> > recursive functions in an interpreter. For example, in the "eval" function:
> >
> >   | ELetRec(var, arg, body, rest) ->
> >       let rec vars' = (var, VClosure(arg, vars', body)) :: vars in
> >       eval vars' rest
> >
> > In SML, I believe you would introduce a mutable reference and give it a
> > dummy value, set up the new scope and assign new scope to the dummy value
> > in order to obtain a cyclic data structure.

> Or represent environments as functions.

> > This is a minor niggle but the OCaml solution seems more elegant to me.

> In a non-lazy language, I would not really call this elegant -- I
> would call it risky.

I would call it risky even in a lazy language.  Having cyclic values
still breaks quite a few properties.  For example, how do you pickle a
cyclic list?  How do you avoid going into an infinite loop while
comparing two cyclic lists?  In SML, at least, cyclic data can be
manipulated correctly, because cycles always go through a mutable ref
or array and you can compare those for identity (rather than just
structure).  This means that one can correctly pickle and compare
cyclic data (and more) and my generics library, for example, does that
(it handles cyclic data correctly in most generics (pickle, ord, eq,
seq, hash, pretty, transform and possibly others I forgot)).

-Vesa Karvonen
0
11/11/2007 7:31:02 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
[...]
> If it doesn't cause problems in practice (e.g. in OCaml code), is it fair to
> call it "risky"?

It does cause problems in practise.  You've just learned how to cope
with the problems (e.g. avoid comparing cyclic values or if the
program goes to an infinite loop, look for a comparison of cyclic
values).

-Vesa Karvonen
0
11/11/2007 7:32:22 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> Vesa Karvonen wrote:
>> > Which details do you find irrelevant?
> 
>> For me:
> 
>> . Uncommon SML extensions
> 
> There are a few extensions that are common to a few SML compilers.
> For example, both SML/NJ and MLton provide an implementation of
> ML-NLFFI, an advanced foreign function interface for calling C from
> SML.

Yes. Common SML extensions are interesting to me because they reflect a
consensus about some deficit of SML, i.e. room for improvement.

>> . Support for obscure platforms like HPPA
> 
> Maybe not you, but I know, for a fact, that support for such obscure
> platforms is important to some companies.

Sure. You are replying to a list of "details that I find irrelevant".

>> . Single notion of equality in SML
>> . Equality looping
> 
> I don't find this irrelevant and I even some O'Caml programmers don't
> find it irrelevant.  For example, a part of a recent ML workshop
> article, Practical Generic Programming in OCaml, is an implementation
> of SML style equality, which really is needed.

That is a circular argument. If it were really needed then it would have
been adopted by the tens of thousands of people now using OCaml rather than
SML.

>> . Anonymous record types
> 
> I find anonymous record types extremely convenient (in comparison to
> generative record types).  Comparing the convenience of structural and
> generative record types is very much like comparing polymorphic
> variants and ordinary variants.

Interesting.

>> I do not believe these points are important and, IMHO, several of the
>> plus points cited for SML are trying to solve problems that don't exist.
> 
> Perhaps the case is just that you don't personally see the importance
> of the problems being solved.

Given the lack of users, it appears that nobody appreciates the importance
of the problems being solved. To put that another way, these are solutions
to problems that don't really exist.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 7:35:18 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> Vesa Karvonen wrote:
>> > Which details do you find irrelevant?
> 
>> For me:
> 
>> . Uncommon SML extensions
> 
> There are a few extensions that are common to a few SML compilers.
> For example, both SML/NJ and MLton provide an implementation of
> ML-NLFFI, an advanced foreign function interface for calling C from
> SML.

Yes. Common SML extensions are interesting to me because they reflect a
consensus about some deficit of SML, i.e. room for improvement.

>> . Support for obscure platforms like HPPA
> 
> Maybe not you, but I know, for a fact, that support for such obscure
> platforms is important to some companies.

Sure. You are replying to a list of "details that I find irrelevant".

>> . Single notion of equality in SML
>> . Equality looping
> 
> I don't find this irrelevant and I even some O'Caml programmers don't
> find it irrelevant.  For example, a part of a recent ML workshop
> article, Practical Generic Programming in OCaml, is an implementation
> of SML style equality, which really is needed.

That is a circular argument. If it were really needed then it would have
been adopted by the tens of thousands of people now using OCaml rather than
SML.

>> . Anonymous record types
> 
> I find anonymous record types extremely convenient (in comparison to
> generative record types).  Comparing the convenience of structural and
> generative record types is very much like comparing polymorphic
> variants and ordinary variants.

Interesting.

>> I do not believe these points are important and, IMHO, several of the
>> plus points cited for SML are trying to solve problems that don't exist.
> 
> Perhaps the case is just that you don't personally see the importance
> of the problems being solved.

Given the lack of users, it appears that nobody appreciates the importance
of the problems being solved. To put that another way, these are solutions
to problems that don't really exist.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 7:37:24 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
[...]
> 64-bit MLton ranges from slower to marginally faster than 32-bit MLton.
> Nothing to do with OCaml.

In other posts, IIRC, you've thrown around numbers where, in one case,
MLton was something like 5 times faster, IIRC, than O'Caml on 32-bits
and, in another case, where MLton was something like 3 times slower,
IIRC, than O'Caml on 64-bits.  So, extrapolating from those numbers,
it would seem that 64-bit MLton would still be faster than O'Caml in
some cases.  So, if MLton isn't competitive at 64-bits, then what does
it make of O'Caml when it actually runs slower at 64-bits on some
programs.

-Vesa Karvonen
0
11/11/2007 7:42:21 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
> [...]
>> 64-bit MLton ranges from slower to marginally faster than 32-bit MLton.
>> Nothing to do with OCaml.
> 
> In other posts, IIRC, you've thrown around numbers where, in one case,
> MLton was something like 5 times faster, IIRC, than O'Caml on 32-bits
> and, in another case, where MLton was something like 3 times slower,
> IIRC, than O'Caml on 64-bits.  So, extrapolating from those numbers,
> it would seem that 64-bit MLton would still be faster than O'Caml in
> some cases.  So, if MLton isn't competitive at 64-bits, then what does
> it make of O'Caml when it actually runs slower at 64-bits on some
> programs.

I'm sure if we try hard enough that we could come up with some pathological
programs that MLton can optimize away but OCaml cannot. Such a program
would probably be heavily abstracted and symbolic (not numerical).

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 7:43:28 PM
In article <fh7l9m$pku$2@oravannahka.helsinki.fi>,
Vesa Karvonen  <vesa.karvonen@cs.helsinki.fi> wrote:
> I would call it risky even in a lazy language.  Having cyclic values
> still breaks quite a few properties.  For example, how do you pickle a
> cyclic list?  How do you avoid going into an infinite loop while
> comparing two cyclic lists?

By adding a reasonably well-behaved extension to support object
identities:

http://www.cs.chalmers.se/~koen/pubs/entry-asian99-lava.html

(Trivial to implement with IORefs and unsafePerformIO.)

Yes, this breaks referential transparency a bit, but it only brings
into the semantics some distinctions that already matter
performance-wise.


Lauri
0
la (473)
11/11/2007 7:44:55 PM
Vesa Karvonen wrote:
> I would call it risky even in a lazy language.  Having cyclic values
> still breaks quite a few properties.  For example, how do you pickle a
> cyclic list?

OCaml does that for you.

> How do you avoid going into an infinite loop while comparing two cyclic
> lists? 

Using OCaml's physical equality.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 7:46:41 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> If it doesn't cause problems in practice (e.g. in OCaml code), is it fair
>> to call it "risky"?
> 
> It does cause problems in practise.  You've just learned how to cope
> with the problems (e.g. avoid comparing cyclic values or if the
> program goes to an infinite loop, look for a comparison of cyclic
> values).

I have never had to look for a comparison of cyclic values => it is not a
practical problem.

I cannot even remember the last time I heard of someone having that problem.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 7:47:57 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
[...]
> > The first is SML's ":" operator for signatures (as opposed to ":>",
> > which corresponds to OCaml's ":").

> I'll look into that, thanks.

I recommend that you read at least one book on SML.  Transparent
signature ascription and its relation to opaque signature ascription
is something that would definitely be discussed in a chapter about the
SML module system.

> MLton takes 22x longer to compile and runs over 2.2x slower than
> OCaml.

Oh, sorry.  In my previously sent post I recalled one number
incorrectly.  I said 3, but the number was actually just 2.2.  So, it
is likely that MLton would still beat the socks of O'Caml in the other
case you've talked about (where MLton was significantly faster than
O'Caml at 32-bits).  So, it would seem that MLton has decent 64-bit
support after all.

-Vesa Karvonen
0
11/11/2007 7:49:05 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> > The first is SML's ":" operator for signatures (as opposed to ":>",
>> > which corresponds to OCaml's ":").
> 
>> I'll look into that, thanks.
> 
> I recommend that you read at least one book on SML.  Transparent
> signature ascription and its relation to opaque signature ascription
> is something that would definitely be discussed in a chapter about the
> SML module system.

I've got ML for the Working Programmer round here somewhere...

>> MLton takes 22x longer to compile and runs over 2.2x slower than
>> OCaml.
> 
> Oh, sorry.  In my previously sent post I recalled one number
> incorrectly.  I said 3, but the number was actually just 2.2.  So, it
> is likely that MLton would still beat the socks of O'Caml in the other
> case you've talked about (where MLton was significantly faster than
> O'Caml at 32-bits).  So, it would seem that MLton has decent 64-bit
> support after all.

If you gather any data on that I'd be very interested.

I think the factor of 3 you were thinking of was new 64-bit MLton being 3.3x
slower than old 32-bit MLton at compiling the ray tracer.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 7:49:59 PM
Jon:
[...]
> Yes. When people create something like Alice ML, do they really reimplement
> the entire thing from scratch?

Many of the SML implementations use completely different
implementation strategies:
- MLton: whole-program compilation to native code
- SML.NET: whole-program compilation to CLR/.NET
- MLKit: regions for memory management
- Alice ML: futures (everywhere), dynamic code import/export
- SML/NJ: continuations, interactive, compiles to native code
- Poly/ML: interactive, compiles to native code
So, there really isn't all that much share.

-Vesa Karvonen
0
11/11/2007 7:56:02 PM
Vesa Karvonen wrote:
>
> I would call it risky even in a lazy language.  Having cyclic values
> still breaks quite a few properties.

Indeed. Formally, it makes datatypes coinductive instead of inductive,
implying that recursive definitions over them are no longer inductive
either - and thus cannot be proven to terminate, for example.

> For example, how do you pickle a
> cyclic list?  How do you avoid going into an infinite loop while
> comparing two cyclic lists?

FWIW, Alice ML allows cyclic data structures, and is able to pickle
them. It also has an equality operator (Store.equiv) that can test
potentially cyclic values for equivalence, i.e. equates structurally
different but observationally equivalent definitions properly, e.g.

  val rec ones = 1::ones
  val rec ones' = 1::1::ones'
  val ones'' = 1::ones'

will all be detected to be equivalent. The downside is that this
operation is very expensive, because it has to perform graph/automaton
minimization. Also, operations like these have to be primitive, you
cannot implement them within the language (unless you have some low-
level pointer equality).

Having said that, I never found these features very useful in practice
(nor harmful, I should add). The reason Alice ML has them is that you
can construct cyclic values with futures and promises anyway, in a
very general manner. Cyclic definitions /can/ be useful in conjunction
with lazy evaluation, though (which futures also give you), where you
naturally deal with infinite data structures.

- Andreas

0
rossberg (600)
11/11/2007 7:57:55 PM
Jon Harrop wrote:
> Vesa Karvonen wrote:
> > Jon Harrop <usenet@jdh30.plus.com> wrote:
> >> > The first is SML's ":" operator for signatures (as opposed to ":>",
> >> > which corresponds to OCaml's ":").
> >
> >> I'll look into that, thanks.
> >
> > I recommend that you read at least one book on SML.  Transparent
> > signature ascription and its relation to opaque signature ascription
> > is something that would definitely be discussed in a chapter about the
> > SML module system.
>
> I've got ML for the Working Programmer round here somewhere...

Unfortunately, that one predates SML'97 by half a year and thus does
not reflect all of its module system - in particular, the :> operator.
For decent discussion of the SML module system, I would recommend
Harper's book, which is online:

    http://www.cs.cmu.edu/~rwh/smlbook/

- Andreas

0
rossberg (600)
11/11/2007 8:08:17 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Jon Harrop wrote:
> > Here's a list of some really useful features added by OCaml:
> > 
> > . Pattern guards

This would be one of the things I'd like to see in MLton from the
Successor ML proposals.

> Some more practical ones as defacto-standard functionality from the stdlib:

> . Pretty printing (Format module)

Available for SML:

http://mlton.org/cgi-bin/viewsvn.cgi/*checkout*/mltonlib/trunk/com/ssh/prettier/unstable/README
http://mlton.org/cgi-bin/viewsvn.cgi/*checkout*/mltonlib/trunk/com/ssh/prettier/unstable/public/prettier.sig

> . Regular expressions

There are several libraries available.  For example, MLton has one and
the SML/NJ utility library has one (you can use the SML/NJ library
with both MLton and SML/NJ, at least).

> . Hash tables with structural hashing

Hash tables can be found from the SML/NJ library.  Fairly convenient
hashing is supported, for example, by my generics library:

  http://mlton.org/cgi-bin/viewsvn.cgi/*checkout*/mltonlib/trunk/com/ssh/generic/unstable/public/value/hash.sig

> . Marshalling (albeit type unsafe)

There are several libraries available for this (SML.NET, SML#, and
MLKit includeshas such a library).  Here is the signature of my
implementation:

  http://mlton.org/cgi-bin/viewsvn.cgi/*checkout*/mltonlib/trunk/com/ssh/generic/unstable/public/value/pickle.sig

Note that a library solution in SML is memory safe.  IOW, you cannot
cause something like a segfault with any of those library.
Furthermore, if you look at the above signature, you'll see (look for
TypeMismatch) that my library provides an easy way to add a dynamic
type check to the (un)pickle(r).

> . GUI API (LablTk)

http://mgtk.sourceforge.net/

-Vesa Karvonen
0
11/11/2007 8:17:06 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:

> I'm sure if we try hard enough that we could come up with some pathological
> programs that MLton can optimize away but OCaml cannot. Such a program
> would probably be heavily abstracted and symbolic (not numerical).

So, O'Caml isn't competitive with large modular (i.e. abstracted)
programs that are heavy on symbolic computation.  The future of O'Caml
seems bad and there isn't a clear way forward.

-Vesa Karvonen
0
11/11/2007 8:19:38 PM
Jon:
> Vesa Karvonen wrote:
> >> > Which details do you find irrelevant?
[...]
> Sure. You are replying to a list of "details that I find irrelevant".

Yes, *you* find them irrelevant.  Others do not necessarily share your
opinion.  Your opinion is not the be all and end all here.

> >> . Single notion of equality in SML
> >> . Equality looping
> > 
> > I don't find this irrelevant and I even some O'Caml programmers don't
> > find it irrelevant.  For example, a part of a recent ML workshop
> > article, Practical Generic Programming in OCaml, is an implementation
> > of SML style equality, which really is needed.

> That is a circular argument.

No, it isn't.  Where is the cycle?

I just pointed out that SML style equality, that works correctly for
both mutable and immutable data, is practically important.  The author
of the mentioned refereed publication thought that it was important.
I would guess that so did the referees, who (based on the list of
people on the program committee) are computer scientists doing
research related to ML.  Otherwise, I would assume, the referees would
have advised the author to remove that section from the paper as
unimportant SML marketing that is void of practical concerns.

> If it were really needed then it would have been adopted by the tens
> of thousands of people now using OCaml rather than SML.

If O'Caml were any good, then it would have been adopted by the
millions of people now programming in Java or C++.

> Given the lack of users, it appears that nobody appreciates the importance
> of the problems being solved.

So, in your mind, appearance is everything, deep understanding and
knowledge are nothing.

-Vesa Karvonen
0
11/11/2007 8:33:00 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
[...]
> I have never had to look for a comparison of cyclic values => it is not a
> practical problem.

I have.  Perhaps your programming experience isn't as conclusive as
you think.  Cyclic data structures are not that uncommon when you
deal, for example, graphs.

-Vesa Karvonen

0
11/11/2007 8:34:36 PM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
> > I would call it risky even in a lazy language.  Having cyclic values
> > still breaks quite a few properties.  For example, how do you pickle a
> > cyclic list?

> OCaml does that for you.

And core dumps.  No, thank you!  I like my code with memory safety.

> > How do you avoid going into an infinite loop while comparing two cyclic
> > lists? 

> Using OCaml's physical equality.

Indeed, that is basically my point.  My point is that laziness, alone,
doesn't solve problems with cyclic values.

-Vesa Karvonen
0
11/11/2007 8:40:55 PM
rossberg@ps.uni-sb.de wrote:
[...]
> > I've got ML for the Working Programmer round here somewhere...

> Unfortunately, that one predates SML'97 by half a year and thus does
> not reflect all of its module system - in particular, the :> operator.

Hmm... Interesting... Browsing my copy of the book...  Looks like :>
on page 265 of the 2nd edition of said book.  Yes, opaque signature
constraints are indeed discussed in the book.  Probably not as
extensively as in some other books/tutorials.

-Vesa Karvonen
0
11/11/2007 8:45:45 PM
In article <13ja560np6nq870@corp.supernews.com>,
Jon Harrop  <usenet@jdh30.plus.com> wrote:
> Anyone with any significant experience of any ML or Haskell will be able to
> understand the statements that I made.
> 
> The difference is quite simple: just look at the pattern matching
> capabilities of Scala compared to SML/OCaml/Haskell/F#.

I'm not familiar with F#, but Scala and (modern) Haskell both have far
more powerful pattern matching capabilities than O'Caml or SML. Both
Scala and Haskell support GADTs, and both support views to an extent:
GHC has pattern guards, and Scala has extractors, which are far more
more powerful and arguably make Scala the winner in this contest. 
O'Caml only has ordinary guards. SML not even that.

O'Caml does support bindings in or-patterns, whereas Scala's
or-patterns cannot bind variables. This is admittedly a point to
O'Caml, since it allows neat stuff like the "balance" function in

http://www.ocaml.info/ocaml_sources/pure-fun-1.0.6/chp3.ml

Still, this just simple syntactic sugar, and hardly enough to outweigh
Scala's extractors.

The level of exhaustiveness checking varies between implementations of
the languages (exhaustiveness checking is usually a quality of
implementation issue instead of a part of the language specification).
But note that it is impossible for any compiler to do exhaustiveness
checking perfectly, in the sense of requiring clauses for all possible
values and not for any others. There are two reasons for this.

Firstly, since guards may contain arbitrary code, it is impossible to
analyze them statically in general, so an exhaustiveness checker is
forced to be conservative and assume that the guard is never passed.
O'Caml does this and yields warnings like this:

Warning P: this pattern-matching is not exhaustive.
(However, some guarded clause may match this value.)

Then, even if the guards actually are complementary and the matching
is exhaustive, one is forced to add a dummy guardless match clause
just to get rid of the warning.

The second reason is that there may well be invariants which the
compiler cannot deduce and which prevent some shapes from ever
appearing. For instance, the standard functional queue:

type 'a queue = Q of 'a list * 'a list

has the invariant that the only values of shape Q([], x) are those
where x is also []. If the compiler requires that there's a match
clause for the shape Q([], _::_) then the programmer is forced to add
an explicit error clause that the compiler could have added
automatically.

This is ultimately a question of attitude. When the compiler cannot be
sure if a match really is in practice exhaustive enough, there are two
options: either assume that the programmer knows what she's doing and
raise a runtime error when a non-matched value is encountered, or
assume that the programmer may have been sloppy and require her to
explicitly raise an error upon encountering an unexpected value in
order to shut up the compiler.

Both attitudes are reasonable enough, so this is hardly a decisive
issue when comparing languages or implementations.


Lauri
0
la (473)
11/11/2007 8:52:45 PM
In article <13jen0rd7u3d173@corp.supernews.com>,
Jon Harrop  <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
> > I don't find this irrelevant and I even some O'Caml programmers don't
> > find it irrelevant.  For example, a part of a recent ML workshop
> > article, Practical Generic Programming in OCaml, is an implementation
> > of SML style equality, which really is needed.
> 
> That is a circular argument. If it were really needed then it would have
> been adopted by the tens of thousands of people now using OCaml rather than
> SML.

By this kind of reasoning, if anything in O'Caml were really needed,
then it would have been adopted by the hundreds of thousands of people
now using Java, C, and whatnot, rather than O'Caml.


Lauri
0
la (473)
11/11/2007 8:56:58 PM
Lauri Alanko <la@iki.fi> writes:
> GHC has pattern guards, and Scala has extractors, which are far more
> more powerful and arguably make Scala the winner in this contest. 
> O'Caml only has ordinary guards. SML not even that.

Could you briefly explain what extractors are?

> But note that it is impossible for any compiler to do exhaustiveness
> checking perfectly, in the sense of requiring clauses for all possible
> values and not for any others. There are two reasons for this.
> 
> Firstly, since guards may contain arbitrary code,

Whether guards (at least pattern guards) can contain arbitrary code is
a matter of the language design, I thought.  If limiting what can be
in a guard pattern means the compiler can check exhaustiveness
reliably, it may be worth the trade-off.  

> This is ultimately a question of attitude. When the compiler cannot be
> sure if a match really is in practice exhaustive enough, there are two
> options: either assume that the programmer knows what she's doing and
> raise a runtime error when a non-matched value is encountered, or
> assume that the programmer may have been sloppy and require her to
> explicitly raise an error upon encountering an unexpected value in
> order to shut up the compiler.
> 
> Both attitudes are reasonable enough, so this is hardly a decisive
> issue when comparing languages or implementations.

I don't see them as being comparable.  The first approach is like
strict type checking.  You can use a conversion function (IntToFloat
or whatever) if you have to, but it's explicit.  The second approach
is like using a type-unsafe language.  I haven't used ML but the
absence of exhaustiveness checking has seemed like a real deficiency
in Haskell.

0
phr.cx (5493)
11/11/2007 9:17:12 PM
In article <7xy7d4lbxj.fsf@ruckus.brouhaha.com>,
Paul Rubin  <http://phr.cx@NOSPAM.invalid> wrote:
> Could you briefly explain what extractors are?

They allow you to define your own patterns. Here's an example: we
define a two-dimensional point type that you can equally well view in
cartesian or in radial form. 

// Firstly, here's the actual implementation of the class. We have
// chosen to use cartesian coordinates here.

class Point private (private val x : double, private val y : double)

// The "private" modifiers mean that outsiders are not allowed to create
// instances of the class or to access its fields. It is thus outwardly a
// completely abstract type.

// The class has an associated object, with the same name, which can
// access its private parts.

object Point {
  // This brings all the static methods from java.lang.Math into scope.
  import java.lang.Math._

  // We now define the first view, as a cartesian product of xy
  // coordinates.
  object Cartesian {

    // This is the constructor, called as Cartesian(x, y). It simply
    // calls the private constructor with the same arguments since the
    // implementation happens to use cartesian coordinates.
    def apply(x : double, y : double) = new Point(x, y)

    // This is the extractor, called when encountering a pattern of
    // shape Cartesian(x,y). The extractor is applied to the matched
    // object, and if the extractor returns Some((x,y)), then the
    // returned values are bound to the variables in the pattern. If
    // the extractor returns None, the match fails. Here we just
    // extract the coordinates directly from the object.
    def unapply(p : Point) = Some((p.x, p.y))
  }

  // A more interesting view is the radial one, since now we have to
  // convert between representations.	  
  object Radial {
    // When Radial(angle, radius) is called, we create a new point by
    // converting radial coordinates to the ones used internally by
    // the implementation.
    def apply(a : double, r : double) = new Point(r * cos(a), 
						  r * sin(a))
    // When we encounter a pattern of shape Radial(a,r), this is how a
    // point is matched and returned values are bound.
    def unapply(p : Point) = Some((atan2(p.y, p.x), 
				   sqrt(p.x * p.x + p.y * p.y)))
  }

  // Finally, here's a silly example of a pattern that can fail.
  object Origin {
    // Origin() returns just the point at origin
    def apply() = new Point(0.0, 0.0)

    // The pattern Origin() matches only a point at origin. Note that
    // we return a boolean here. This is a special case for nullary
    // extractors.
    def unapply(p : Point) = p.x == 0.0 && p.y == 0.0
  }
}  

Now we can use these different views of points interchangably. In the
interactive prompt, we first import stuff into scope:

scala> import Point._
import Point._
scala> import java.lang.Math._
import java.lang.Math._
scala> import Console._
import Console._

We can then construct a point in one way:

scala> val p1 = Cartesian(2,1)
p1: Point = Point@62fcf06c

And match it in another:

scala> p1 match {
     | case Origin() => println("Origin")
     | case Radial(a,r) => println("Angle: " + a + ", Radius: " + r)
     | }
Angle: 0.4636476090008061, Radius: 2.23606797749979

Note that the match against Origin() failed, but the next pattern
succeeded.

An extractor pattern may itself contain other patterns. The values
that the extractor returns are matched against those. Hence:

scala> Radial(PI/2, 4) match {
     | case Cartesian(x, 0) => println("On x-axis!")
     | case _ => println("Not on x-axis!")
     | }
Not on x-axis!

But when the extractor returns a zero as the second component, then
the match succeeds:

scala> Radial(0, 4) match {
     | case Cartesian(x, 0) => println("On x-axis!")
     | case _ => println("Not on x-axis!")
     | }
On x-axis!

Hope this cleared things up somewhat.

> > Both attitudes are reasonable enough, so this is hardly a decisive
> > issue when comparing languages or implementations.
> 
> I don't see them as being comparable.  The first approach is like
> strict type checking.  You can use a conversion function (IntToFloat
> or whatever) if you have to, but it's explicit.  The second approach
> is like using a type-unsafe language.

No. Both approaches are safe: the semantics are well defined even in
the case of a missing match clause: then a run-time error is raised.

Instead, a better analogue would be having _implicit_ conversions
between types. This can also be done in various well-defined and
type-safe ways. It buys some convenience and conciseness at the cost
of making it possible to accidentally shoot yourself in the foot when
you really didn't _intend_ to have something converted. Taken to
extremes, this of course leads to monstrosities like C++. There's
always a tradeoff.


Lauri
0
la (473)
11/11/2007 10:23:41 PM
Lauri Alanko <la@iki.fi> writes:
> > Could you briefly explain what extractors are?
> They allow you to define your own patterns. Here's an example:...

Thanks for this very detailed explanation; I'm going to have to wait
til after lunch to read it carefully.

> > I don't see them as being comparable.  The first approach is like
> > strict type checking.  You can use a conversion function (IntToFloat
> > or whatever) if you have to, but it's explicit.  The second approach
> > is like using a type-unsafe language.
> 
> No. Both approaches are safe: the semantics are well defined even in
> the case of a missing match clause: then a run-time error is raised.
> Instead, a better analogue would be having _implicit_ conversions
> between types....

Well, how about it's like static vs. dynamic typing.  I.e. the idea is
to be assured of flagging any mismatch at compile time, instead of
getting a runtime effect.
0
phr.cx (5493)
11/11/2007 10:39:06 PM
rossberg@ps.uni-sb.de wrote:
> Vesa Karvonen wrote:
[...]
> > For example, how do you pickle a
> > cyclic list?  How do you avoid going into an infinite loop while
> > comparing two cyclic lists?

> FWIW, Alice ML allows cyclic data structures, and is able to pickle
> them.

If you have an infinite list produced by a lazy computation like, in
Haskell notation, [1, 2, ...], then can Alice ML also serialize such a
list producing a finite pickle of it?  (I would think that it would be
technically possible, because Alice ML can pickle closures.)

> It also has an equality operator (Store.equiv) that can test
> potentially cyclic values for equivalence, i.e. equates structurally
> different but observationally equivalent definitions properly, e.g.

>   val rec ones = 1::ones
>   val rec ones' = 1::1::ones'
>   val ones'' = 1::ones'

> will all be detected to be equivalent.

Interesting.  As you know, in SML'97 one can only build cyclic data
through mutable objects (refs or arrays).  For testing my pickling
generic, I implemented a structural equality predicate with a similar
property:

  http://mlton.org/cgi-bin/viewsvn.cgi/*checkout*/mltonlib/trunk/com/ssh/generic/unstable/public/value/seq.sig

-Vesa Karvonen
0
11/11/2007 10:54:22 PM
Vesa Karvonen wrote:
> rossberg@ps.uni-sb.de wrote:
> [...]
> > > I've got ML for the Working Programmer round here somewhere...
>
> > Unfortunately, that one predates SML'97 by half a year and thus does
> > not reflect all of its module system - in particular, the :> operator.
>
> Hmm... Interesting... Browsing my copy of the book...  Looks like :>
> on page 265 of the 2nd edition of said book.

You are right, it actually is mentioned. Sorry, I misremembered. The
actual problem, however, is that it is not explained properly -
appearently, everything on SML'97 modules was added last minute. In
particular, there is a paragraph on the alleged limitations of opaque
ascription - which actually is incorrect, thanks to transparent type
specs and "where type" refinement, which are also mentioned only in
passing as "recent proposals". But instead, the totally obsolete
"abstype" is suggested and discussed as the primary means for
achieving type abstraction.

So, I strongly suggest a different source if you want to learn about
SML modules (which is unfortunate, because I otherwise like the
book...).

- Andreas

0
rossberg (600)
11/11/2007 11:19:23 PM
Vesa Karvonen wrote:
> Jon:
>> Yes. When people create something like Alice ML, do they really
>> reimplement the entire thing from scratch?
> 
> Many of the SML implementations use completely different
> implementation strategies:
> - MLton: whole-program compilation to native code
> - SML.NET: whole-program compilation to CLR/.NET
> - MLKit: regions for memory management
> - Alice ML: futures (everywhere), dynamic code import/export
> - SML/NJ: continuations, interactive, compiles to native code
> - Poly/ML: interactive, compiles to native code
> So, there really isn't all that much share.

Is there a clear winner?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 11:37:11 PM
Vesa Karvonen wrote:
> rossberg@ps.uni-sb.de wrote:
> > Vesa Karvonen wrote:
> [...]
> > > For example, how do you pickle a
> > > cyclic list?  How do you avoid going into an infinite loop while
> > > comparing two cyclic lists?
>
> > FWIW, Alice ML allows cyclic data structures, and is able to pickle
> > them.
>
> If you have an infinite list produced by a lazy computation like, in
> Haskell notation, [1, 2, ...], then can Alice ML also serialize such a
> list producing a finite pickle of it?  (I would think that it would be
> technically possible, because Alice ML can pickle closures.)

It is technically possible, and we have indeed discussed this
possibility. We refrained from it in favour of a consistent treatment
of futures (all futures are uniformly requested by pickling, like
everywhere else) and a more predictable behaviour (silently attempting
to pickle lazy suspensions might result in larger pickles than
expected, and more seriously, unexpected failure due to resources
contained in the closure - in particular, the fact that every cross-
component binding inherently is a lazy future makes these show
stoppers).

> > It also has an equality operator (Store.equiv) that can test
> > potentially cyclic values for equivalence, i.e. equates structurally
> > different but observationally equivalent definitions properly, e.g.
>
> >   val rec ones = 1::ones
> >   val rec ones' = 1::1::ones'
> >   val ones'' = 1::ones'
>
> > will all be detected to be equivalent.
>
> Interesting.  As you know, in SML'97 one can only build cyclic data
> through mutable objects (refs or arrays).  For testing my pickling
> generic, I implemented a structural equality predicate with a similar
> property:

Right, in plain SML achieving this roperty is relatively
straightforward, because you never have to fold back a cycle - the
problem basically reduces to bottom-up hash-consing. Whereas with
coinductive types it is equivalent to full-scale automaton
minimization.

- Andreas

0
rossberg (600)
11/11/2007 11:39:15 PM
On 11 Nov 2007 20:56:58 GMT, Lauri Alanko wrote:

> In article <13jen0rd7u3d173@corp.supernews.com>,
> Jon Harrop  <usenet@jdh30.plus.com> wrote:
>> Vesa Karvonen wrote:
>>> I don't find this irrelevant and I even some O'Caml programmers don't
>>> find it irrelevant.  For example, a part of a recent ML workshop
>>> article, Practical Generic Programming in OCaml, is an implementation
>>> of SML style equality, which really is needed.
>> 
>> That is a circular argument. If it were really needed then it would have
>> been adopted by the tens of thousands of people now using OCaml rather than
>> SML.
> 
> By this kind of reasoning, if anything in O'Caml were really needed,
> then it would have been adopted by the hundreds of thousands of people
> now using Java, C, and whatnot, rather than O'Caml.
> 
> 
> Lauri

If any programming language was needed, it would have been adopted by the
billions of people now not programming at all.
-- 
Alexey Romanov

"My species were swimming the seas when you Earth types were
still sitting around in stone huts scribbling calculus equations
with graphite sticks."

Freefall <http://freefall.purrsia.com/ff1300/fv01224.htm>
0
alexey_r (3)
11/11/2007 11:46:52 PM
Vesa Karvonen wrote:
> Jon:
>> Vesa Karvonen wrote:
>> >> > Which details do you find irrelevant?
> [...]
>> Sure. You are replying to a list of "details that I find irrelevant".
> 
> Yes, *you* find them irrelevant.  Others do not necessarily share your
> opinion.  Your opinion is not the be all and end all here.

Non-sequitur: of course my opinion is the be all and end all here because
this is a list of my opinions. Indeed, that was the whole point...

>> >> . Single notion of equality in SML
>> >> . Equality looping
>> > 
>> > I don't find this irrelevant and I even some O'Caml programmers don't
>> > find it irrelevant.  For example, a part of a recent ML workshop
>> > article, Practical Generic Programming in OCaml, is an implementation
>> > of SML style equality, which really is needed.
>>
>> That is a circular argument.
> 
> No, it isn't.  Where is the cycle?
> 
> I just pointed out that SML style equality, that works correctly for
> both mutable and immutable data, is practically important.

Why do you believe it is practically important?

> The author 
> of the mentioned refereed publication thought that it was important.
> I would guess that so did the referees, who (based on the list of
> people on the program committee) are computer scientists doing
> research related to ML.  Otherwise, I would assume, the referees would
> have advised the author to remove that section from the paper as
> unimportant SML marketing that is void of practical concerns.

Your measure of practical relevance is whether or not you can publish an
academic paper describing something?

>> If it were really needed then it would have been adopted by the tens
>> of thousands of people now using OCaml rather than SML.
> 
> If O'Caml were any good, then it would have been adopted by the
> millions of people now programming in Java or C++.

Non-sequitur: you've changed "needed" to "good".

>> Given the lack of users, it appears that nobody appreciates the
>> importance of the problems being solved.
> 
> So, in your mind, appearance is everything, deep understanding and
> knowledge are nothing.

If testing is "appearance" and "deep understanding and knowledge" means
talking to yourself on the MLKit developers list, yes.

You are implying that you value a language that works in theory over one
that works in practice, which is silly.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 11:54:14 PM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
> [...]
>> I have never had to look for a comparison of cyclic values => it is not a
>> practical problem.
> 
> I have.  Perhaps your programming experience isn't as conclusive as
> you think.  Cyclic data structures are not that uncommon when you
> deal, for example, graphs.

You might say I wrote the book on it...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/11/2007 11:59:34 PM
Lauri Alanko wrote:
> In article <13jen0rd7u3d173@corp.supernews.com>,
> Jon Harrop  <usenet@jdh30.plus.com> wrote:
>> Vesa Karvonen wrote:
>> > I don't find this irrelevant and I even some O'Caml programmers don't
>> > find it irrelevant.  For example, a part of a recent ML workshop
>> > article, Practical Generic Programming in OCaml, is an implementation
>> > of SML style equality, which really is needed.
>> 
>> That is a circular argument. If it were really needed then it would have
>> been adopted by the tens of thousands of people now using OCaml rather
>> than SML.
> 
> By this kind of reasoning, if anything in O'Caml were really needed,
> then it would have been adopted by the hundreds of thousands of people
> now using Java, C, and whatnot, rather than O'Caml.

Except that nobody claimed that OCaml is "needed" because that would be
stupid.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 12:00:20 AM
In article <<fh7p0s$t0n$2@oravannahka.helsinki.fi>>,
Vesa Karvonen <vesa.karvonen@cs.helsinki.fi> wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
> [...]
>> I have never had to look for a comparison of cyclic values => it is not a
>> practical problem.
> 
> I have.  Perhaps your programming experience isn't as conclusive as
> you think.  Cyclic data structures are not that uncommon when you
> deal, for example, graphs.

You can't usually use the cyclic data feature of Ocaml in these cases.
You can only use it to build a cyclic data structure when you
statically know what all of the cycles are. Since this is hardly ever
the case, the cyclic data feature is hardly ever used. And a feature
that is hardly ever used hardly ever causes problems, for obvious
reasons. ;)

Concretely, if you are writing an interpreter, you can't use it to
implement mutual recursion. If you're building a finite automaton from
a regexp, you can't use it to build a DFA. If you're building a
control flow graph, you can't use it because you don't know where the
branch targets might lead. 

So this feature of Ocaml is basically a useless frill. It doesn't
cause any problems, because it can't really be put to serious use.


-- 
Neel R. Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
11/12/2007 12:09:42 AM
Lauri Alanko wrote:
> In article <13ja560np6nq870@corp.supernews.com>,
> Jon Harrop  <usenet@jdh30.plus.com> wrote:
>> Anyone with any significant experience of any ML or Haskell will be able
>> to understand the statements that I made.
>> 
>> The difference is quite simple: just look at the pattern matching
>> capabilities of Scala compared to SML/OCaml/Haskell/F#.
> 
> I'm not familiar with F#, but Scala and (modern) Haskell both have far
> more powerful pattern matching capabilities than O'Caml or SML.

Scala cannot even check patterns over built in types for exhaustiveness.

> Both 
> Scala and Haskell support GADTs, and both support views to an extent:
> GHC has pattern guards, and Scala has extractors, which are far more
> more powerful and arguably make Scala the winner in this contest.
> O'Caml only has ordinary guards.

And or-patterns, polymorphic variants, regular expressions, views, character
ranges, destructuring, arrays etc...

> SML not even that. 

SML's pattern matching also exceeds the capabilities of Scala's in the same
way.

> O'Caml does support bindings in or-patterns, whereas Scala's
> or-patterns cannot bind variables. This is admittedly a point to
> O'Caml, since it allows neat stuff like the "balance" function in
> 
> http://www.ocaml.info/ocaml_sources/pure-fun-1.0.6/chp3.ml
> 
> Still, this just simple syntactic sugar, and hardly enough to outweigh
> Scala's extractors.

Views are already available in OCaml and F#:

  http://martin.jambon.free.fr/micmatch-manual.html#htoc10

Outside interoperability with a host platform, they are of little use.

> The level of exhaustiveness checking varies between implementations of
> the languages (exhaustiveness checking is usually a quality of
> implementation issue instead of a part of the language specification).

I believe exhaustiveness checking is mandated by the SML definition.

> But note that it is impossible for any compiler to do exhaustiveness
> checking perfectly, in the sense of requiring clauses for all possible
> values and not for any others. There are two reasons for this.
> 
> Firstly, since guards may contain arbitrary code, it is impossible to
> analyze them statically in general, so an exhaustiveness checker is
> forced to be conservative and assume that the guard is never passed.
> O'Caml does this and yields warnings like this:
> 
> Warning P: this pattern-matching is not exhaustive.
> (However, some guarded clause may match this value.)
> 
> Then, even if the guards actually are complementary and the matching
> is exhaustive, one is forced to add a dummy guardless match clause
> just to get rid of the warning.
> 
> The second reason is that there may well be invariants which the
> compiler cannot deduce and which prevent some shapes from ever
> appearing. For instance, the standard functional queue:
> 
> type 'a queue = Q of 'a list * 'a list
> 
> has the invariant that the only values of shape Q([], x) are those
> where x is also []. If the compiler requires that there's a match
> clause for the shape Q([], _::_) then the programmer is forced to add
> an explicit error clause that the compiler could have added
> automatically.

While true, this is not justification for failing to implement
exhaustiveness and redundancy checking. After all, if you follow that line
of thinking then you give up on all forms of static checking.

> This is ultimately a question of attitude. When the compiler cannot be
> sure if a match really is in practice exhaustive enough, there are two
> options: either assume that the programmer knows what she's doing and
> raise a runtime error when a non-matched value is encountered, or
> assume that the programmer may have been sloppy and require her to
> explicitly raise an error upon encountering an unexpected value in
> order to shut up the compiler.
> 
> Both attitudes are reasonable enough, so this is hardly a decisive
> issue when comparing languages or implementations.

On the contrary, Scala's poor support for basic pattern matching features
found in all MLs adversely impacts the productivity of the whole language.

Until Scala supports these basic features I think it is absurd to claim that
Scala's pattern matching is supreme. For me it is not even preferable.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 12:18:26 AM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> I'm sure if we try hard enough that we could come up with some
>> pathological programs that MLton can optimize away but OCaml cannot. Such
>> a program would probably be heavily abstracted and symbolic (not
>> numerical).
> 
> So, O'Caml isn't competitive with large modular (i.e. abstracted)
> programs that are heavy on symbolic computation.  The future of O'Caml
> seems bad and there isn't a clear way forward.

If you gather data and prove your theory then you can catch up.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 12:19:59 AM
In article <<1194811075.456164.294670@v2g2000hsf.googlegroups.com>>,
rossberg@ps.uni-sb.de <rossberg@ps.uni-sb.de> wrote:
> Vesa Karvonen wrote:
>>
>> I would call it risky even in a lazy language.  Having cyclic values
>> still breaks quite a few properties.
>
> Indeed. Formally, it makes datatypes coinductive instead of inductive,
> implying that recursive definitions over them are no longer inductive
> either - and thus cannot be proven to terminate, for example.

This isn't quite the case, is it? In a call-by-value language, cyclic
data structures can't do any computation to get the next value, which
makes them rational trees (ie, finite graphs) rather than true
coinductive types. For example, we still won't have a cbv list of the
form

   [0, 1, 2, 3, 4, 5, 6, ...]

even though it's a perfectly sensible/annoying inhabitant of the type
of coinductive lists.


-- 
Neel R. Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
11/12/2007 12:19:59 AM
Neelakantan Krishnaswami wrote:
> You can't usually use the cyclic data feature of Ocaml in these cases.
> You can only use it to build a cyclic data structure when you
> statically know what all of the cycles are. Since this is hardly ever
> the case, the cyclic data feature is hardly ever used. And a feature
> that is hardly ever used hardly ever causes problems, for obvious
> reasons. ;)
> 
> Concretely, if you are writing an interpreter, you can't use it to
> implement mutual recursion. If you're building a finite automaton from
> a regexp, you can't use it to build a DFA. If you're building a
> control flow graph, you can't use it because you don't know where the
> branch targets might lead.
> 
> So this feature of Ocaml is basically a useless frill. It doesn't
> cause any problems, because it can't really be put to serious use.

I think that is a much more justifiable perspective, yes. I do still use it
though...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 12:21:19 AM
Paul Rubin wrote:
> Lauri Alanko <la@iki.fi> writes:
>> > Could you briefly explain what extractors are?
>> They allow you to define your own patterns. Here's an example:...
> 
> Thanks for this very detailed explanation; I'm going to have to wait
> til after lunch to read it carefully.

Like so many other examples of Scala's extractors and Wadler's views,
Lauri's example can be written much more simply and elegantly as a
conversion function.

In practice, Scala's extractors (or views in OCaml, or active patterns in F#
etc.) are of extremely limited utility. I am only aware of one example
where they actually do something useful: implementing lazy pattern matching
over lazy lists in an eager language.

>> > I don't see them as being comparable.  The first approach is like
>> > strict type checking.  You can use a conversion function (IntToFloat
>> > or whatever) if you have to, but it's explicit.  The second approach
>> > is like using a type-unsafe language.
>> 
>> No. Both approaches are safe: the semantics are well defined even in
>> the case of a missing match clause: then a run-time error is raised.
>> Instead, a better analogue would be having _implicit_ conversions
>> between types....
> 
> Well, how about it's like static vs. dynamic typing.  I.e. the idea is
> to be assured of flagging any mismatch at compile time, instead of
> getting a runtime effect.

The Scala approach certainly undermines reliability because it fails to
perform several basic checks, yes.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 12:31:37 AM
Jon:
> Vesa Karvonen wrote:
> > Many of the SML implementations use completely different
> > implementation strategies:
> > - MLton: whole-program compilation to native code
> > - SML.NET: whole-program compilation to CLR/.NET
> > - MLKit: regions for memory management
> > - Alice ML: futures (everywhere), dynamic code import/export
> > - SML/NJ: continuations, interactive, compiles to native code
> > - Poly/ML: interactive, compiles to native code

A few more:
- HaMLet: "implementation is intended to be as direct a translation of
the language formalisation found in the Definition of Standard ML [1]
as possible"
- TILT: "self-checking compiler for Standard ML that uses Typed
Intermediate Languages"
- Moscow ML: light-weight implementation, bytecode compiler
- SML#: "SML# supports the following practically important new features:

    * Seamless Interoperablility with C
    * Record polymorphism
    * Rank1 polymorphism"

> Is there a clear winner?

Yes, people who appreciate diversity and understand that one size
doesn't fit all.  I really don't see why there should be a "clear
winner".  The implementation of SML compilers isn't a competition as
such.

-Vesa Karvonen
0
11/12/2007 12:47:28 AM
Neelakantan Krishnaswami wrote:
> In article <<1194811075.456164.294670@v2g2000hsf.googlegroups.com>>,
> rossberg@ps.uni-sb.de <rossberg@ps.uni-sb.de> wrote:
> > Vesa Karvonen wrote:
> >>
> >> I would call it risky even in a lazy language.  Having cyclic values
> >> still breaks quite a few properties.
> >
> > Indeed. Formally, it makes datatypes coinductive instead of inductive,
> > implying that recursive definitions over them are no longer inductive
> > either - and thus cannot be proven to terminate, for example.
>
> This isn't quite the case, is it? In a call-by-value language, cyclic
> data structures can't do any computation to get the next value, which
> makes them rational trees (ie, finite graphs) rather than true
> coinductive types. For example, we still won't have a cbv list of the
> form
>
>    [0, 1, 2, 3, 4, 5, 6, ...]
>
> even though it's a perfectly sensible/annoying inhabitant of the type
> of coinductive lists.

OK, you are right, with CBV you only get a tiny subclass of
coinductive types. It's only mildly larger than the class of inductive
types, and I agree with you that the delta isn't really useful for
much. And the requirement to construct such values as a constant using
let rec even rules out almost all remaining use cases.

Actually, I think it would be a good idea if ML had efficient single
assignment references for those cases where you need to construct
cycles but have no intention of mutating them - which I reckon applies
to most of them.

- Andreas

0
rossberg (600)
11/12/2007 1:35:44 AM
Jon:
> Vesa Karvonen wrote:
> > So, O'Caml isn't competitive with large modular (i.e. abstracted)
> > programs that are heavy on symbolic computation.  The future of O'Caml
> > seems bad and there isn't a clear way forward.

> If you gather data and prove your theory then you can catch up.

You already provided the data.  According to your data, O'Caml's good
performance is limited to hand tuned toy raytracers and even then it
is beaten by dynamically typed languages like Scheme.

-Vesa Karvonen
0
11/12/2007 1:58:22 AM
Neelakantan Krishnaswami <neelk@cs.cmu.edu> wrote:
> In article <<fh7p0s$t0n$2@oravannahka.helsinki.fi>>,
> Vesa Karvonen <vesa.karvonen@cs.helsinki.fi> wrote:
> > Jon:
> > [...]
> >> I have never had to look for a comparison of cyclic values => it is not a
> >> practical problem.
> > 
> > I have.  Perhaps your programming experience isn't as conclusive as
> > you think.  Cyclic data structures are not that uncommon when you
> > deal, for example, graphs.

> You can't usually use the cyclic data feature of Ocaml in these cases.

Note that I am just talking about the comparison of cyclic data
structures.  The way in which you have built them doesn't matter in
O'Caml:

$ ocaml
        Objective Caml version 3.09.2

# type still_a_problem = T of still_a_problem option ref ;;
type still_a_problem = T of still_a_problem option ref
# let r = ref None ;;
val r : '_a option ref = {contents = None}
# let see = T r ;;
val see : still_a_problem = T {contents = None}
# r := Some see ;;
- : unit = ()
# see < see ;;

WRROOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOMMM!!!

That is the sound of O'Caml, going blazingly fast, nearly as fast as
with 64-bits of rope, and hanging itself into an infinite loop of
death.  :-)

-Vesa Karvonen
0
11/12/2007 2:33:14 AM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
[...]
> > Yes, *you* find them irrelevant.  Others do not necessarily share your
> > opinion.  Your opinion is not the be all and end all here.

> Non-sequitur: of course my opinion is the be all and end all here because
> this is a list of my opinions. Indeed, that was the whole point...

"here" refers to the newsgroup: comp.lang.functional.

> > I just pointed out that SML style equality, that works correctly for
> > both mutable and immutable data, is practically important.

> Why do you believe it is practically important?

Well, because, as a singular example, you need an equality that
actually works, as opposed to O'Caml's notion equality that doesn't
work and even eagerly goes into an infinite loop, to be able to
serialize data while also reducing the size of serialized data by
taking advantage of sharing.

> Your measure of practical relevance is whether or not you can publish an
> academic paper describing something?

Nope.

> >> If it were really needed then it would have been adopted by the tens
> >> of thousands of people now using OCaml rather than SML.
> > 
> > If O'Caml were any good, then it would have been adopted by the
> > millions of people now programming in Java or C++.

> Non-sequitur: you've changed "needed" to "good".

Oops, you really got me this time.  Oh, boy!  Let me just rephrase
then:

If O'Caml were really needed, then it would have been adopted by the
millions of people now programming in Java or C++.

So, by your own method of reasoning, people don't really need O'Caml.
Indeed, why would they?  You've just spent days here telling how jolly
good O'Caml is at being slower than Scheme and how "really useful"
O'Caml's feature to go into infinite loops is.  No wonder people don't
need it.

> >> Given the lack of users, it appears that nobody appreciates the
> >> importance of the problems being solved.
> > 
> > So, in your mind, appearance is everything, deep understanding and
> > knowledge are nothing.

> If testing is "appearance" and "deep understanding and knowledge"
> means talking to yourself on the MLKit developers list, yes.

Read your own words: "it appears that nobody appreciates the
importance of the problems being solved."

  http://www.m-w.com/dictionary/appreciate
  "to grasp the nature, worth, quality, or significance of"

In other words, you are saying that those tens of thousands of people
now using O'Caml don't understand the importance of the problems being
solved by SML.  How could you say it any more clearly?  In your
opinion, O'Caml's virtue is that its users have trouble understanding
basic concepts of programming languages and the problems they solve.

> You are implying that you value a language that works in theory over one
> that works in practice, which is silly.

Nope.  I prefer a language that works, period.  Not a language whose
"really useful" feature is to go into an infinite loop.

-Vesa Karvonen
0
11/12/2007 3:20:50 AM
Jon:
[...]
> Have you tried OCaml, Scala and F#?

I've tried O'Caml.  That was many years ago.  It kept dumping core and
going into infinite loops.  It has had those "really useful"
"standard" features for many years now with no apparent appreciation
of the problems or activity at solving them.  It seems that O'Caml is
going nowhere and the future of O'Caml looks grim indeed.

-Vesa Karvonen

P.S. I never realized how much fun this is!  Trying to be fair, trying
hard to verify all facts, doing careful analysis, ... who needs that
crap.

0
11/12/2007 3:54:29 AM
Vesa Karvonen wrote:
> Jon:
>> Have you tried OCaml, Scala and F#?
> 
> I've tried O'Caml.  That was many years ago.

What did you write?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 10:49:51 AM
Vesa Karvonen wrote:
> That is the sound of O'Caml, going blazingly fast, nearly as fast as
> with 64-bits of rope, and hanging itself into an infinite loop of
> death.  :-)

You can write infinite loops in any language...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 10:53:05 AM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> Vesa Karvonen wrote:
> [...]
>> > Yes, *you* find them irrelevant.  Others do not necessarily share your
>> > opinion.  Your opinion is not the be all and end all here.
> 
>> Non-sequitur: of course my opinion is the be all and end all here because
>> this is a list of my opinions. Indeed, that was the whole point...
> 
> "here" refers to the newsgroup: comp.lang.functional.

No, "here" referred to my post about "details that I find irrelevant".

>> > I just pointed out that SML style equality, that works correctly for
>> > both mutable and immutable data, is practically important.
> 
>> Why do you believe it is practically important?
> 
> Well, because, as a singular example, you need an equality that
> actually works, as opposed to O'Caml's...

OCaml's equality clearly works.

>> >> If it were really needed then it would have been adopted by the tens
>> >> of thousands of people now using OCaml rather than SML.
>> > 
>> > If O'Caml were any good, then it would have been adopted by the
>> > millions of people now programming in Java or C++.
> 
>> Non-sequitur: you've changed "needed" to "good".
> 
> Oops, you really got me this time.  Oh, boy!

Indeed.

>> >> Given the lack of users, it appears that nobody appreciates the
>> >> importance of the problems being solved.
>> > 
>> > So, in your mind, appearance is everything, deep understanding and
>> > knowledge are nothing.
> 
>> If testing is "appearance" and "deep understanding and knowledge"
>> means talking to yourself on the MLKit developers list, yes.
> 
> Read your own words: "it appears that nobody appreciates the
> importance of the problems being solved."
> 
>   http://www.m-w.com/dictionary/appreciate
>   "to grasp the nature, worth, quality, or significance of"
> 
> In other words, you are saying that those tens of thousands of people
> now using O'Caml don't understand the importance of the problems being
> solved by SML.

Not quite: I'm saying they realise that these problems you claim to be
solving have no practical applications. Had you solved practically
important problems, people would use your stuff.

>> You are implying that you value a language that works in theory over one
>> that works in practice, which is silly.
> 
> Nope.  I prefer a language that works, period.

Then you'll be needing a user base to test your implementation.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 11:00:01 AM
Vesa Karvonen wrote:
> Jon:
>> Vesa Karvonen wrote:
>> > So, O'Caml isn't competitive with large modular (i.e. abstracted)
>> > programs that are heavy on symbolic computation.  The future of O'Caml
>> > seems bad and there isn't a clear way forward.
> 
>> If you gather data and prove your theory then you can catch up.
> 
> You already provided the data...

No, I didn't. You must test your hypothesis by gathering data. If you do, I
will be interested to see your results.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 11:01:27 AM
rossberg@ps.uni-sb.de wrote:
> Actually, I think it would be a good idea if ML had efficient single
> assignment references for those cases where you need to construct
> cycles but have no intention of mutating them - which I reckon applies
> to most of them.

That sounds like a good idea.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 11:02:17 AM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> Vesa Karvonen wrote:
>> > I've tried O'Caml.  That was many years ago. It kept dumping core and
>> > going into infinite loops. 
> 
>> What did you write?
> 
> My first O'Caml project was a (simple) compiler for an ML-style (H-M
> type inference, GC, variant types, ...) scripting language design.

Did you ask for help with your dumping core problem?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 11:04:34 AM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
> > Jon:
> >> Have you tried OCaml, Scala and F#?
> > 
> > I've tried O'Caml.  That was many years ago.

> What did you write?

My first O'Caml project was a (simple) compiler for an ML-style (H-M
type inference, GC, variant types, ...) scripting language design.

-Vesa Karvonen
0
11/12/2007 11:07:40 AM
Jon:
> You can write infinite loops in any language...

But only O'Caml has that as a really useful ad hoc built-in feature.
Therein lies a design flaw of O'Caml --- and it is just one of many.
O'Caml has even that really useful built-in feature to dump core.  It
is a really useful memory unsafe and type unsafe feature.

-Vesa Karvonen
0
11/12/2007 11:14:39 AM
Jon:
> Vesa Karvonen wrote:
> > Jon:
> >> Vesa Karvonen wrote:
> >> > I've tried O'Caml.  That was many years ago. It kept dumping core and
> >> > going into infinite loops. 
> > 
> >> What did you write?
> > 
> > My first O'Caml project was a (simple) compiler for an ML-style (H-M
> > type inference, GC, variant types, ...) scripting language design.

> Did you ask for help with your dumping core problem?

I asked help with the going into an infinite loop problem.  I think I
ran into that in unit test code --- not in the compiler proper.  I'm
sure you can find my name from the O'Caml mailing list archives.

However, probably the most important thing I noticed during that
period was that fixing problems in O'Caml was not a priority to the
developers.  For example, I noticed issues in ocamllex/ocamlyacc.
They used global parser state at the time --- probably still do ---
and that there was no convenient syntax for threading state
(functionally).  Some guy (I forget the name, just google) ---
actually, I think there were *two* guys, independently of each other
--- had already written fixes for those problems, but the O'Caml
developers just ignored the patch(es).  I also noticed the protective
and restrictive licensing of O'Caml:

  http://camlcvs.inria.fr/cgi-bin/cvsweb/~checkout~/ocaml/LICENSE?rev=1.17.4.3.2.1;content-type=text%2Fplain

O'Caml's license prevents other people from distributing patched
versions of O'Caml.  It looked like to me that O'Caml was going
nowhere and that its developers did not appreciate the efforts of
others to improve the situation.  In fact, I was totally right!
Having checked just now, ocamlyacc still seems to use global state.
You know, therein lies a design flaw!  Oh, boy!  The future of O'Caml
looks awfully bad and there doesn't seem to be any kind of progress
forward.  I really prefer much more robust, better designed, and
engineered languages than O'Caml.  With O'Caml you get the worst of
all world.

Trust me, I haven't even nearly exhausted my list of concerning
problems of social kind with the development of O'Caml or badly
designed and engineered aspects of the O'Caml language.  And the best
part is that all of it is true.  Until now, I've just preferred to try
and be fair.  That is over now.

-Vesa Karvonen
0
11/12/2007 11:58:44 AM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
> > Jon Harrop <usenet@jdh30.plus.com> wrote:
> >> Vesa Karvonen wrote:
> > [...]
> >> > Yes, *you* find them irrelevant.  Others do not necessarily share your
> >> > opinion.  Your opinion is not the be all and end all here.
[...]
> > "here" refers to the newsgroup: comp.lang.functional.

> No, "here" referred to my post about "details that I find irrelevant".

Sorry, but the word "here" comes from my sentence, so I get to decide
the thing that it refers to.

> OCaml's equality clearly works.

You mean, "works" by going into an infinite loop.

> Not quite: I'm saying they realise that these problems you claim to be
> solving have no practical applications. Had you solved practically
> important problems, people would use your stuff.

I'm not talking about my stuff here.  I'm talking about SML style
equality.  By your reasoning, it solves a practical problem, because
the author of the O'Caml paper used it to solve his other practical
problems.  In other words, SML style equality was used as a solution
to a practical problem.

-Vesa Karvonen
0
11/12/2007 12:06:55 PM
Jon:
[...]
> Have you tried OCaml, Scala and F#?

Oh, one more thing.  I haven't tried F# myself, but I have this story
I'd like to share with you.  You see, not so long ago, I was at this
meeting called CUFP'07 (http://cufp.galois.com/).  I think there were
more than a hundred people in the audience, so I'm sure that at least
some people can verify my story.  It happened that during the last
session I sat next to none other than Don Syme (ask him, maybe he
remembers).  In the discussion session the topic was roughly that how
can we as a community help to increase the use of functional languages
in the industry.  You know, I don't normally drag other people into
arguments like this, but Don Syme voiced an opinion during that
discussion session and since it was addressed to the whole audience
rather than being a private communication, I see no harm in telling
what he said.  You see, the gist of what he said is that we should
refraing from language comparisons between functional languages,
because such language comparisons are pure and absolute poison and do
not advance our purposes.  Yes, he really used the words "absolute
poison" and I'm sure that despite the fact that I probably sat closer
to hit at that moment than anyone else, there were at least some
people in the audience who appreciated what Don Syme said.

How does that make you feel, Jon?  Have a lovely monday!

-Vesa Karvonen
0
11/12/2007 1:27:52 PM
In article <<fh8e1a$h12$1@oravannahka.helsinki.fi>>,
Vesa Karvonen <vesa.karvonen@cs.helsinki.fi> wrote:
>Neelakantan Krishnaswami <neelk@cs.cmu.edu> wrote:
>> 
>> You can't usually use the cyclic data feature of Ocaml in these cases.
> 
> Note that I am just talking about the comparison of cyclic data
> structures.  The way in which you have built them doesn't matter in
> O'Caml.

Oh, yes, you're right.

I would say this is because Ocaml gets ref equality wrong. Comparing
the contents of refs is a totally bizarre choice, since it's slower,
more prone to error, and not even an equivalence relation on values.

I suppose Leroy and company weren't worrying very much about
imperative programming, which demonstrates a certain level of good
taste. ;)


-- 
Neel R. Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
11/12/2007 4:06:03 PM
In article <<1194831344.386941.50410@57g2000hsv.googlegroups.com>>,
rossberg@ps.uni-sb.de <rossberg@ps.uni-sb.de> wrote:
> Neelakantan Krishnaswami wrote:
>> In article <<1194811075.456164.294670@v2g2000hsf.googlegroups.com>>,
>> rossberg@ps.uni-sb.de <rossberg@ps.uni-sb.de> wrote:
>> > Indeed. Formally, it makes datatypes coinductive instead of inductive,
>> > implying that recursive definitions over them are no longer inductive
>> > either - and thus cannot be proven to terminate, for example.
>>
>> This isn't quite the case, is it? In a call-by-value language, cyclic
>> data structures can't do any computation to get the next value, which
>> makes them rational trees (ie, finite graphs) rather than true
>> coinductive types. For example, we still won't have a cbv list of the
>> form
>>
>>    [0, 1, 2, 3, 4, 5, 6, ...]
>>
>> even though it's a perfectly sensible/annoying inhabitant of the type
>> of coinductive lists.
> 
> OK, you are right, with CBV you only get a tiny subclass of
> coinductive types. It's only mildly larger than the class of inductive
> types, and I agree with you that the delta isn't really useful for
> much. And the requirement to construct such values as a constant using
> let rec even rules out almost all remaining use cases.

Hey, don't concede too quickly!

The rational trees correspond to finite graphs, which are not exactly
unheard-of in computer science. :) I think this makes them a very
important intermediate class between inductive and coinductive types,
because they're a form of "infinite" (really, circular) data structure
that all sorts of fixed point and automata-minimization techniques
work well on.

It's the "must be constants defined with let rec" rule that makes them
difficult to work with. If the type system knew about them, I would
hope that restriction could be lifted.

> Actually, I think it would be a good idea if ML had efficient single
> assignment references for those cases where you need to construct
> cycles but have no intention of mutating them - which I reckon applies
> to most of them.

That would be a really nice way of doing it, yes.

-- 
Neel R. Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
11/12/2007 4:30:53 PM
Neelakantan Krishnaswami wrote:
>
> The rational trees correspond to finite graphs, which are not exactly
> unheard-of in computer science. :) I think this makes them a very
> important intermediate class between inductive and coinductive types,
> because they're a form of "infinite" (really, circular) data structure
> that all sorts of fixed point and automata-minimization techniques
> work well on.
>
> It's the "must be constants defined with let rec" rule that makes them
> difficult to work with. If the type system knew about them, I would
> hope that restriction could be lifted.

It's also the fact that there is no good way to process these things.
The nodes in this graph have no identity - unless you have physical
equality (impure) or encode identity yourself (tedious). Thus the
usual graph algorithms don't apply. And once you go to an encoding you
might as well use a different structure.

- Andreas

0
rossberg (600)
11/12/2007 4:51:58 PM
In article <7xwssoif05.fsf@ruckus.brouhaha.com>,
Paul Rubin  <http://phr.cx@NOSPAM.invalid> wrote:
> Well, how about it's like static vs. dynamic typing.  I.e. the idea is
> to be assured of flagging any mismatch at compile time, instead of
> getting a runtime effect.

It is true that exhaustiveness checking is a form of static analysis
that enforces the absence of a certain kind of run-time behavior. The
problem is that, like some type systems, it is not powerful enough,
and rejects some valid code, forcing the programmer to explicitly
circumvent it.

For example, consider classic (pre-generics) Java. There, I can easily
store a string in a vector:

	ArrayList l = new ArrayList();
	l.add("Foo");

but immediately afterwards, I cannot directly retrieve the string:

	String s = l.get(0); // bad

This is a perfectly safe operation, since we the first item in the
vector actually is a string, but since the type system is too weak,
we're forced to add a vacuous runtime check just to satisfy the
compiler:

	String s = (String) l.get(0);

A dynamic cast could also be expressed with a typecase form, if Java
had one:

       String s = typecase l.get(0) {
                    String s => s;
                    Object _ => throw new ClassCastException();
                  };

This is effectively the same problem that we get with exhaustiveness
checking: we're forced to explicitly handle a case that we believe
cannot (or at least shouldn't) occur. For instance, in Haskell, we can
define the sign function like this:

sgn :: Int -> Int
sgn x | x > 0   = 1
sgn x | x == 0  = 0
sgn x | x < 0   = -1

If checkable exhaustiveness were enforced, because the compiler cannot
see that the guards actually cover all the possible cases, then we'd
be forced to add a dummy clause:

sgn _           = error "Shouldn't happen!"

The question is whether this kind of checking provides enough benefits
to outweigh the inconvenience that it incurs. I don't think there is
an obvious, universally applicable answer to this, some people's
claims notwithstanding.

But personally, I find that at least the type system of classic Java
provides so few benefits and requires so much hassle with casting that
I prefer untyped languages over it.


Lauri
0
la (473)
11/12/2007 10:03:12 PM
In article <slrnfjgufb.ehp.neelk@gs3106.sp.cs.cmu.edu>,
Neelakantan Krishnaswami  <neelk@cs.cmu.edu> wrote:
> I would say this is because Ocaml gets ref equality wrong. Comparing
> the contents of refs is a totally bizarre choice, since it's slower,
> more prone to error, and not even an equivalence relation on values.

It's not quite bizarre: O'Caml's "="-operator corresponds to Scheme's
equal?, which is certainly a useful operation even though it's
arguably ill-defined in the presence of mutation. Similarly, O'Caml's
"==" corresponds to eq?, in that it reveals implementation-defined
distinctions between semantically equal values.

SML's equality corresponds to eqv?, which is the "correct" equality in
Scheme. Strangely enough, even though schemers have this available,
they seem to often use a combination of eq? and equal?, much like
O'Camlers.


Lauri
0
la (473)
11/12/2007 10:23:51 PM
Lauri Alanko <la@iki.fi> wrote:
[...]
> It is true that exhaustiveness checking is a form of static analysis
> that enforces the absence of a certain kind of run-time behavior. The
> problem is that, like some type systems, it is not powerful enough,
> and rejects some valid code, forcing the programmer to explicitly
> circumvent it.

Personally, I very much like to have exhaustiveness checking.  In my
experience, the extra work to handle all patterns is, in most cases,
so small (usually zero) that the overall impact is insignificant.

There are some tedious special cases (and I did count these in my
assessment of overall impact), however, for which I'd like to see
language support.  As I'm sure you know, SML has syntactic sugar for
record field selectors.  I would also like to have similar syntactic
sugar for datatype variant "projectors".  IOW, you could write, for
example,

  %Constructor

and, in the case of an unary constructor, get the function

  fn Constructor x => SOME x | _ => NONE

or, in the case of a nullary constructor, the function

  fn Constructor => SOME () | _ => NONE .

Alternatively, instead of returning an option, the projector could
raise Match.

If you think about it, this syntactic sugar eliminates the worst case
of having to write an extra case for exhaustiveness.  The worst case,
of course, occurs when you would otherwise have just a single case.

> For instance, in Haskell, we can define the sign function like this:

> sgn :: Int -> Int
> sgn x | x > 0   = 1
> sgn x | x == 0  = 0
> sgn x | x < 0   = -1

But that would an unnecessarily verbose way to define it.  Much better
to write it less verbosely either as

sgn :: Int -> Int
sgn x | x > 0   = 1
sgn x | x < 0   = -1
sgn _           = 0

or as

sgn :: Int -> Int
sgn x = if x < 0 then -1 else if x > 0 then 1 else 0

and exhaustiveness would be ensured.

-Vesa Karvonen
0
11/12/2007 10:32:34 PM
Lauri Alanko <la@iki.fi> wrote:
[...]
> SML's equality corresponds to eqv?, which is the "correct" equality in
> Scheme. Strangely enough, even though schemers have this available,
> they seem to often use a combination of eq? and equal?, much like
> O'Camlers.

I think that this is basically a misguided attempt at optimization.
IOW, you use eq? (or O'Caml's equivalent) to perform efficient pointer
equality.  The problem with this is that nothing prevents even a
moderately smart implementation from doing that optimization for you.

-Vesa Karvonen
0
11/12/2007 10:37:54 PM
Vesa Karvonen <vesa.karvonen@cs.helsinki.fi> wrote:
> Lauri Alanko <la@iki.fi> wrote:
> [...]
> > SML's equality corresponds to eqv?, which is the "correct" equality in
> > Scheme. Strangely enough, even though schemers have this available,
> > they seem to often use a combination of eq? and equal?, much like
> > O'Camlers.

> I think that this is basically a misguided attempt at optimization.

Actually, the problems run deeper in Scheme.  In Scheme (R5RS),
practically all data types (pairs, lists, strings, vectors, ...) are
mutable objects with identity, but you often *wish* to treat them as
immutable values without identity.  So, the programmer actually has to
know, through some extra linguistic means, whether to treat specific
data types as mutable or immutable.  SML basically doesn't have this
problem, because it supports a wide range of immutable data types, so
you basically never have to abuse mutable data types for that purpose
(and doing that would usually just complicate things --- so it doesn't
happen accidentally), and a single notion of equality is appropriate.
Indeed, I recall writing a post to this group (but I think the post
never got through) a while back countering claims that in an
imperative language you often have to copy data structures to avoid
the possibility of breaking encapsulation / abstraction through
mutation.  While I know that in some languages, like Java and C++,
this is a real issue, it basically never happens in SML, because if
you don't want others to mutate your data, you just use immutable
data!

-Vesa Karvonen
0
11/12/2007 11:00:13 PM
In article <fhaka2$jg3$1@oravannahka.helsinki.fi>,
Vesa Karvonen  <vesa.karvonen@cs.helsinki.fi> wrote:
> Personally, I very much like to have exhaustiveness checking.  In my
> experience, the extra work to handle all patterns is, in most cases,
> so small (usually zero) that the overall impact is insignificant.

Certainly it's not a very big hindrance, even if its usefulness is
limited. I'm not so much arguing against exhaustiveness checking as
against bashing the lack of exhaustiveness checking. :)

>   %Constructor
> 
> and, in the case of an unary constructor, get the function
> 
>   fn Constructor x => SOME x | _ => NONE

Looks like an extractor. :)

> > For instance, in Haskell, we can define the sign function like this:
> 
> > sgn :: Int -> Int
> > sgn x | x > 0   = 1
> > sgn x | x == 0  = 0
> > sgn x | x < 0   = -1
> 
> But that would an unnecessarily verbose way to define it.  Much better
> to write it less verbosely either as
> 
> sgn :: Int -> Int
> sgn x | x > 0   = 1
> sgn x | x < 0   = -1
> sgn _           = 0

Ah, but that is the very worst thing you can do. In the name of
satisfying exhaustiveness checking (and perhaps also in the name of
efficiency), you have transformed your program in a way whose
semantics-preservedness depends on your belief that the clauses
actually are exhaustive, and after the transformation this property is
no longer checked! If you have made an error, and there actually is a
case that you have not handled, then now it won't be detected at all
because the overlooked case is subsumed by the last fallback clause.

It would be optimal if the compiler could statically ensure that our
clauses are in practice exhaustive, but failing that, there must be a
run-time check for the cases that we haven't handled. Either an
implicit one added by the compiler, or an an explicit one that we have
added to satisfy the exhaustiveness checker. But getting rid of the
check altogether is unwise, and if exhaustiveness checking encourages
doing this then that's a point against it.


Lauri
0
la (473)
11/12/2007 11:02:49 PM
Lauri Alanko wrote:
>
> The question is whether this kind of checking provides enough benefits
> to outweigh the inconvenience that it incurs. I don't think there is
> an obvious, universally applicable answer to this, some people's
> claims notwithstanding.

Well, I don't know. When having complex, nested patterns over
algebraic datatypes I certainly want to rely on the compiler checking
exhaustiveness for me. That's the classic closed-world scenario
algebraic datatypes were invented for. I can imagine other use cases
of pattern matching where this is less of an issue, but these are
usually situations where you have an open-world assumption, and thus
need a default case anyway.

- Andreas

0
rossberg (600)
11/12/2007 11:05:24 PM
Lauri Alanko wrote:
> It is true that exhaustiveness checking is a form of static analysis
> that enforces the absence of a certain kind of run-time behavior. The
> problem is that, like some type systems, it is not powerful enough,
> and rejects some valid code, forcing the programmer to explicitly
> circumvent it.

No, it is powerful enough in a wide variety of cases and that is precisely
why it is so useful: you can rephrase your code and get the compiler to
prove that you have eliminated sources of run-time error.

You cannot do that in languages like Scala, which forces you into the world
of dynamic checking and unit testing.

> But personally, I find that at least the type system of classic Java
> provides so few benefits and requires so much hassle with casting that
> I prefer untyped languages over it.

That seems to be the justification for creating rather naff languages
targetting the JVM: they only need to be better than Java. I think that is
a great shame and I look forward to the ocamljava project...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/12/2007 11:48:01 PM
Lauri Alanko <la@iki.fi> wrote:
[...]
> Looks like an extractor. :)

(I haven't read that post yet.)

> > > For instance, in Haskell, we can define the sign function like this:
                       ^^^^^^^

> > > sgn :: Int -> Int
             ^^^^^^^^^^
> > > sgn x | x > 0   = 1
> > > sgn x | x == 0  = 0
> > > sgn x | x < 0   = -1
> > 
> > But that would an unnecessarily verbose way to define it.  Much better
> > to write it less verbosely either as
> > 
> > sgn :: Int -> Int
> > sgn x | x > 0   = 1
> > sgn x | x < 0   = -1
> > sgn _           = 0

> Ah, but that is the very worst thing you can do. In the name of
> satisfying exhaustiveness checking (and perhaps also in the name of
> efficiency),

Nope.  The real motivation is neither exhaustiveness checking nor
efficiency.  The motivation is just to avoid unnecessary verbosity.

Comparing against zero is redundant here, because there are no
integers other than 0 that are neither less than nor greater than 0.

I'm talking about your example in particular.  Not some hypothetical
example.  You could interpret this as saying that your example is
flawed.  (To make a more interesting example, introduce a new ad hoc
data type, and argue that you'll probably want to add new variants to
it, so a catch-all pattern is inappropriate.  I'll then show you how
to write it better.)

> you have transformed your program in a way whose
> semantics-preservedness depends on your belief that the clauses
> actually are exhaustive, and after the transformation this property
> is no longer checked!

It wasn't checked statically earlier either.

If this was a pacemaker, the patient would have died anyway as soon as
the "impossible happened" (in GHC parlance :-).

> If you have made an error, and there actually is a case that you
> have not handled, then now it won't be detected at all because the
> overlooked case is subsumed by the last fallback clause.

But this is a moot point when you start with a language that doesn't
require exhaustiveness checking in the first place (your example was
explicitly in Haskell and also explicitly used the Int type).  Of
course, if you *do have* exhaustiveness checking, and the data type
you are matching against isn't cast in stone (meaning that you'll
never modifying it --- for example, I know full well that I'll never
modify the bool, option and order datatypes in SML and I don't mind
using catch-all patterns with those datatypes), then you shouldn't
introduce a catch-all pattern, except...  (waiting for your next
example)

-Vesa Karvonen
0
11/12/2007 11:48:46 PM
Vesa Karvonen wrote:
> You see, the gist of what he said is that we should
> refraing from language comparisons between functional languages,
> because such language comparisons are pure and absolute poison and do
> not advance our purposes.  Yes, he really used the words "absolute
> poison" and I'm sure that despite the fact that I probably sat closer
> to hit at that moment than anyone else, there were at least some
> people in the audience who appreciated what Don Syme said.

Don told me that story himself and we have discussed it at length.

That view interprets the functional programming communities as neighboring
tribes and language comparisons as breeding contempt that might invoke a
war. Such a model leads to unstable dynamics where a language can be wiped
out by a language comparison war.

I believe reality is very different: functional programming languages are
niche products in a market. Consequently, they draw their users almost
entirely from mainstream programming languages and hardly at all from each
other. This has two main consequences:

1. Functional programming languages do not compete for users.
Quantitatively, their rate of competition is proportional to their market
share squared, which is absolutely tiny for all functional programming
languages.

2. Unfavorable publicity increases sales. Favorable publicity increases
sales a lot.

As my livelihood depends upon it, I can have studied these models in detail
(quantitatively) and I have more information to go on (actual product
sales) than most other people. My conclusion is that "all publicity is good
publicity" for functional programming languages at the moment and I think
this is quite reasonable.

Look at my ray tracer language comparison, for example. Thousands of people
visit it every month. Its got lots of code in lots of functional
programming languages. Its an interesting article voted for by dozens of
people on Digg, DZone and even Reddit.

Haskell was doing unfavorable: 3x slower than the front-runners. I
hypothesized that laziness was crippling its performance. Was
that "absolute poison"? Did I destroy the Haskell community? No, of course
not. Now that you put it in real terms, the idea is absurd. Did I even dent
the number of people migrating to Haskell? No, I increased it by giving
Haskell any publicity at all among mainstream programmers.

Then Lennart Augustsson revamps the Haskell implementations, making them
shorter and much faster, particularly when using the latest GHC-6.8 with
its new whizz-bang features:

http://augustss.blogspot.com/2007/11/benchmarking-ray-tracing-haskell-vs.html

Don Stewart is quick to post on Reddit "Benchmarking ray tracing: Haskell
vs. OCaml: the Haskell programs are always smaller and faster":

http://programming.reddit.com/info/5zzmu/comments/

Oh man, what a kick in the teeth! Is the whole OCaml community going to roll
over and die? Will the Haskell community drag Xavier up a mountain for a
ritual sacrifice? No, of course not. Our website hits go through the roof
again and lots more mainstream programmers think "wow, these functional
languages really aren't dead at all" and start learning about functional
programming.

Next, I'll publish the results on my site showing that Don can't compare
numbers correctly and Haskell can only match OCaml's performance on
Lennart's old Apple Macintosh because it runs his Core 2 Duo in legacy
32-bit mode. And so on and so forth.

The only potential problem with the language comparisons is when people get
nasty and people get upset.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 1:23:01 AM
Vesa Karvonen wrote:
> Jon:
>> You can write infinite loops in any language...
> 
> But only O'Caml has that as a really useful ad hoc built-in feature.
> Therein lies a design flaw of O'Caml --- and it is just one of many.
> O'Caml has even that really useful built-in feature to dump core.  It
> is a really useful memory unsafe and type unsafe feature.

That outlook is fine provided you only want to write self-contained SML
programs. If anyone wants to interface with the outside world then they are
screwed. What is the state of web services and OpenGL 2 in SML, for
example?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 1:38:57 AM
Lauri Alanko <la@iki.fi> writes:
> > sgn :: Int -> Int
> > sgn x | x > 0   = 1
> > sgn x | x < 0   = -1
> > sgn _           = 0
> 
> ... you have transformed your program in a way whose
> semantics-preservedness depends on your belief that the clauses
> actually are exhaustive, and after the transformation this property is
> no longer checked!

I think the right spirit is something like:

    sgn :: Int -> Int
    sgn x = let v = compare x 0 in
            case v of
              LT -> -1
              EQ -> 0
              GT -> 1
0
phr.cx (5493)
11/13/2007 2:50:13 AM
Vesa Karvonen wrote:
> Lauri Alanko <la@iki.fi> wrote:
>> SML's equality corresponds to eqv?, which is the "correct" equality in
>> Scheme. Strangely enough, even though schemers have this available,
>> they seem to often use a combination of eq? and equal?, much like
>> O'Camlers.
> 
> I think that this is basically a misguided attempt at optimization.

What is the SML equivalent of this:

  [|1;2;3|] < [|2;3;4|]

or this:

  nan == nan

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 3:01:25 AM
Vesa Karvonen wrote:
> Jon Harrop <usenet@jdh30.plus.com> wrote:
>> OCaml's equality clearly works.
> 
> You mean, "works" by going into an infinite loop.

I mean works by not segfaulting like MLton, or running at all unlike SML/NJ
or being used by more people than the whole of SML or... you can pick one.
The fact is, your assertion that OCaml's equality "doesn't work" is beyond
silly. Rather than repeating it, I'd advise you to pretend that it wasn't
you who said it. Make up an imaginary friend, maybe someone from the MLKit
dev list, and pretend it was them.

>> Not quite: I'm saying they realise that these problems you claim to be
>> solving have no practical applications. Had you solved practically
>> important problems, people would use your stuff.
> 
> I'm not talking about my stuff here.

Very well. Let's discuss your users...

> I'm talking about SML style  
> equality.  By your reasoning, it solves a practical problem, because
> the author of the O'Caml paper used it to solve his other practical
> problems.  In other words, SML style equality was used as a solution
> to a practical problem.

That is your reasoning, not mine. My reasoning was to point out that
academic papers are a suboptimal place to find out whether or not a problem
is of practical significance. Indeed, they are arguably the worst possible
place to look.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 3:49:52 AM
On Nov 13, 4:01 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> What is the SML equivalent of this:
>
>   [|1;2;3|] < [|2;3;4|]

You'd use

    Array.collate op<

> or this:
>
>   nan == nan

Presumably, Real.?= is more likely to do what you want (note that two
IEEE nans can have different representations). In fact, this seems to
be a good example of a bogus use of the wrong equality.

0
rossberg (600)
11/13/2007 5:45:15 AM
Vesa Karvonen <vesa.karvonen@cs.helsinki.fi> wrote:
[...]
> Indeed, I recall writing a post to this group (but I think the post
> never got through) a while back countering claims that in an
> imperative language you often have to copy data structures to avoid
> the possibility of breaking encapsulation / abstraction through
> mutation.  While I know that in some languages, like Java and C++,
> this is a real issue, it basically never happens in SML, because if
> you don't want others to mutate your data, you just use immutable
> data!

I think that the post that I replied to was this one:

  http://groups.google.fi/group/comp.lang.functional/msg/88df0e2201c776ed

Some people in Finland might have seen my reply, but I think that for
some reason my post never got beyond the servers at University of
Helsinki.  ...  Here is a copy of my original reply:

From: Vesa Karvonen <vesa.karvonen@cs.helsinki.fi>
Subject: Re: ML vs. Lisp
Newsgroups: comp.lang.functional
References: <7xy7n73s74.fsf_-_@ruckus.brouhaha.com>   <7xsldebq8v.fsf@ruckus.brouhaha.com> <090220072236508674%timcmay@removethis.got.net> <7xwt2qsdor.fsf@ruckus.brouhaha.com> <87veia189l.fsf@ixod.org>
 <u11wky2ife.fsf@hod.lan.m-e-leypold.de> <7x1wkwv9i8.fsf@ruckus.brouhaha.com> <45d0e3f6$0$8748$ed2619ec@ptn-nntp-reader02.plus.net> <7xejovx7b0.fsf@ruckus.brouhaha.com> <eqr399$a3r$1@ulysses.news.tisca
li.de> <7xzm7isslh.fsf@ruckus.brouhaha.com> <eqt4hq$j1b$1@online.de>
Date: Tue, 13 Feb 2007 21:03:11 -0000

Joachim Durchholz <jo@durchholz.org> wrote:
[...]
> No, it's usually the opposite: in a language with mutation, you're
> either forced to use all data in a single-threaded fashion (which places
> quite tight constraints on the design), or you have to copy entire data
> structures "just to make sure it doesn't get overwritten".

Just to clarify things a bit as this is a thread titled "ML vs. Lisp".

In Standard ML, only ref cells and arrays are mutable and everything
else is immutable (strings, vectors, lists, tuples, records,
datatypes, ...).  While SML can be described as a "language with
mutation" it definitely does not mean that the only choices were to
copy entire data structures or use them in a single threaded fashion
as you seem to imply.  Indeed, I don't recall ever copying data in SML
"just to make sure it doesn't get overwritten".  In SML, one uses
mutable data in interfaces precisely when one wants it to be mutable.

What you are saying basically applies only to misdesigned imperative
languages (most of them) such as C and, arguably, Scheme and most
Lisps.  This is because all (compound) data in those language is
mutable by default and there may not even be any way to restrict
mutability.  This indeed means that sometimes data must to be copied
just to make sure that abstraction barriers can not be broken.  What
is even worse (a huge WTF of language design) is that some of those
languages, including C and Scheme, make it possible to write programs
whose behaviour is undefined, because they would modify literal data
(e.g. string literals) specified by the program text.

-Vesa Karvonen
0
11/13/2007 7:12:53 AM
Jon Harrop <usenet@jdh30.plus.com> wrote:
> Vesa Karvonen wrote:
> > Lauri Alanko <la@iki.fi> wrote:
> >> SML's equality corresponds to eqv?, which is the "correct" equality in
           ^^^^^^^^                                             ^^^^^^^^
> >> Scheme. Strangely enough, even though schemers have this available,
> >> they seem to often use a combination of eq? and equal?, much like
> >> O'Camlers.
> > 
> > I think that this is basically a misguided attempt at optimization.

> What is the SML equivalent of this:

I just checked what these evaluate to in O'Caml, so...

>   [|1;2;3|] < [|2;3;4|]

....in SML, I would just write:

  true

> or this:

>   nan == nan

and here I would also write:

  true .

But, more seriously, this would seem appropriate:

  http://en.wikipedia.org/wiki/Chewbacca_defense

-Vesa Karvonen
0
11/13/2007 8:35:15 AM
Vesa Karvonen <vesa.karvonen@cs.helsinki.fi> writes:

> Jon Harrop <usenet@jdh30.plus.com> wrote:

>> What is the SML equivalent of this:
>
>>   nan == nan
>
> and here I would also write:
>
>   true .

Actually, I would write "raise Illegal", where Illegal would signal an
illegal operation.  Comparing two NaNs is no more defined than
dividing by 0.

	Torben
0
torbenm610 (36)
11/13/2007 10:55:34 AM
Torben �gidius Mogensen <torbenm@app-2.diku.dk> wrote:
> Vesa Karvonen <vesa.karvonen@cs.helsinki.fi> writes:
> > Jon:

> >> What is the SML equivalent of this:
> >>   nan == nan
> >   true .

> Actually, I would write "raise Illegal", where Illegal would signal an
> illegal operation.  Comparing two NaNs is no more defined than
> dividing by 0.

It seems to defined in O'Caml:

  http://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html

Relevant excerpts:

  "compare x y returns 0 if x is equal to y, a negative integer if x
  is less than y, and a positive integer if x is greater than y. The
  ordering implemented by compare is compatible with the comparison
  predicates =, < and > defined above, with one difference on the
  treatment of the float value nan. Namely, the comparison predicates
  treat nan as different from any other float value, including itself;
  while compare treats nan as equal to itself and less than any other
  float value. This treatment of nan ensures that compare defines a
  total ordering relation."

and

  "e1 == e2 tests for physical equality of e1 and e2. On integers and
  characters, physical equality is identical to structural
  equality. On mutable structures, e1 == e2 is true if and only if
  physical modification of e1 also affects e2. On non-mutable
  structures, the behavior of (==) is implementation-dependent;
  however, it is guaranteed that e1 == e2 implies compare e1 e2 = 0."

-Vesa Karvonen
0
11/13/2007 11:25:20 AM
On 2007-11-13, in comp.lang.functional, Vesa Karvonen wrote, quoting the
O'Caml documentation:
>   "e1 == e2 tests for physical equality of e1 and e2. On integers and
>   characters, physical equality is identical to structural
>   equality. On mutable structures, e1 == e2 is true if and only if
>   physical modification of e1 also affects e2. On non-mutable
>   structures, the behavior of (==) is implementation-dependent;
>   however, it is guaranteed that e1 == e2 implies compare e1 e2 = 0."

In order to conclude from the fact that compare nan nan = 0,
that nan == nal evaluates to true in O'Caml, we'd need the reverse
implication, that compare e1 e2 = 0 implies e1 == e2.

-- 
Aatu Koskensilta (aatu.koskensilta@xortec.fi)

"Wovon man nicht sprechen kann, daruber muss man schweigen"
 - Ludwig Wittgenstein, Tractatus Logico-Philosophicus
0
11/13/2007 11:31:05 AM
Aatu Koskensilta <aatu.koskensilta@xortec.fi> wrote:
> On 2007-11-13, in comp.lang.functional, Vesa Karvonen wrote, quoting the
> O'Caml documentation:
> >   "e1 == e2 tests for physical equality of e1 and e2. On integers and
> >   characters, physical equality is identical to structural
> >   equality. On mutable structures, e1 == e2 is true if and only if
> >   physical modification of e1 also affects e2. On non-mutable
> >   structures, the behavior of (==) is implementation-dependent;
> >   however, it is guaranteed that e1 == e2 implies compare e1 e2 = 0."

> In order to conclude from the fact that compare nan nan = 0,
> that nan == nal evaluates to true in O'Caml, we'd need the reverse
> implication, that compare e1 e2 = 0 implies e1 == e2.

Excellent point!  So, following in the practical footsteps of C, it is
left undefined in O'Caml.  Note that nan == nan does evaluate to true
in the implementation of O'Caml that I have on my machine.  Also note
that the value nan is part of O'Caml's library, so this isn't
surprising (the nans on both sides are bitwise equal).  I haven't
tested what the result would be if one would actually compare
different NaN values produced by several different floating point
computations.  I would not be surprised if one could also get false
from such a comparison.  Like I've said before, O'Caml tends to get
these things wrong and there doesn't seem to be any kind of progress
in fixing them.  The future of O'Caml looks practically undefined.

-Vesa Karvonen
0
11/13/2007 11:47:43 AM
 rossberg@ps.uni-sb.de wrote:
> On Nov 13, 4:01 am, Jon Harrop <use...@jdh30.plus.com> wrote:
>>
>> What is the SML equivalent of this:
>>
>>   [|1;2;3|] < [|2;3;4|]
> 
> You'd use
> 
>     Array.collate op<

Thank you! So:

  a = b

where a and b are vectors becomes something like:

  Array.forall op= a b

Given that you create infix operators for vector operations in OCaml anyway
it doesn't seem too bad to use something like "=|" for vector equality.

>> or this:
>>
>>   nan == nan
> 
> Presumably, Real.?= is more likely to do what you want (note that two
> IEEE nans can have different representations). In fact, this seems to
> be a good example of a bogus use of the wrong equality.

Interesting...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 12:28:32 PM
On Nov 13, 1:28 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> Thank you! So:
>
>   a = b
>
> where a and b are vectors becomes something like:
>
>   Array.forall op= a b

Actually, if a and b are literally "vectors" then you can simply write
a = b in SML, too. That's because SML vectors are immutable (as
opposed to arrays).

- Andreas

0
rossberg (600)
11/13/2007 1:55:32 PM
Jon:
> Except that nobody claimed that OCaml is "needed" because that would be
> stupid.

For once we can agree.  O'Caml isn't needed.  That would be stupid.

-Vesa Karvonen
0
11/13/2007 2:38:46 PM
 rossberg@ps.uni-sb.de wrote:
> On Nov 13, 1:28 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
>> Thank you! So:
>>
>>   a = b
>>
>> where a and b are vectors becomes something like:
>>
>>   Array.forall op= a b
> 
> Actually, if a and b are literally "vectors" then you can simply write
> a = b in SML, too. That's because SML vectors are immutable (as
> opposed to arrays).

I meant vectors in the mathematical sense so I think the SML type "float
vector" would be fine (I don't mutate them).

Incidentally, if anyone does another round of ML languages I'd highly
recommend adding complex, vector and matrix numeric types with literals (at
least for complexes) and make the ad-hoc polymorphic operators work on
those as well. These are all very useful in F#.

Since SML, the ML family of languages have shown that they are awesome tools
for scientific computing, particularly when combined with something like
OpenGL. F# is really leading the pack in terms of these capabilities now.
You can retrofit much of this stuff onto OCaml but having different
operators for 2d vectors, 3d vectors and arbitrary vectors is silly. From
our benchmarks, compilers must unbox complex numbers but not necessarily
low-dimensional vectors (even 2D ones). Having internal representations
that are compatible with C is also extremely useful for FFI, e.g. when
manipulating OpenGL vertex buffer objects you want your ML compiler to use
a different allocator but make the data look exactly like an ordinary
array/vector.

Also, a 32-bit float type is quite valuable as a storage format (OCaml
doesn't support this) partly for memory consumption but also for FFI.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 4:46:54 PM
 rossberg@ps.uni-sb.de wrote:
> It's also the fact that there is no good way to process these things.
> The nodes in this graph have no identity - unless you have physical
> equality (impure) or encode identity yourself (tedious).

Going off on a tangent here. OCaml provides physical equality but not
physical ordering. This boils down to comparing pointers than can be moved
by the GC. Consequently, to avoid linear searches using physical equality,
values are sometimes tagged with identities "manually" which, as you say,
is tedious.

I can think of a couple of "solutions" but they bring their own problems:

.. prevent the GC from moving (i.e. no compaction) but this might have
adverse effects like fragmentation.

.. tag all values with identities but this sounds like memory-bloating
overkill.

If a better language existed, how might it solve this problem without
introducing other problems?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 4:57:36 PM
Vesa Karvonen wrote:
> However, probably the most important thing I noticed during that
> period was that fixing problems in O'Caml was not a priority to the
> developers.  For example, I noticed issues in ocamllex/ocamlyacc.
> They used global parser state at the time --- probably still do ---
> and that there was no convenient syntax for threading state
> (functionally).  Some guy (I forget the name, just google) ---
> actually, I think there were *two* guys, independently of each other
> --- had already written fixes for those problems, but the O'Caml
> developers just ignored the patch(es).  I also noticed the protective
> and restrictive licensing of O'Caml:
> 
>  
http://camlcvs.inria.fr/cgi-bin/cvsweb/~checkout~/ocaml/LICENSE?rev=1.17.4.3.2.1;content-type=text%2Fplain

Yes. Lack of reentrant parsing was a problem for many people (not me) but
the inability to fix such problems is a much more serious concern, IMHO.

> O'Caml's license prevents other people from distributing patched
> versions of O'Caml.

Yes. You must distribute their original sources and your changes as patches
to be applied. I also fail to see how this helps anyone. There are tools to
help with such situations but why should we have to bother.

> It looked like to me that O'Caml was going 
> nowhere and that its developers did not appreciate the efforts of
> others to improve the situation.  In fact, I was totally right!
> Having checked just now, ocamlyacc still seems to use global state.

OCamlyacc has sufficed for my work but many people seem to have migrated to
Menhir, which offers many benefits including reentrancy:

  http://cristal.inria.fr/~fpottier/menhir/

I actually like the camlp4 parsers but they need documentation.

> You know, therein lies a design flaw!  Oh, boy!  The future of O'Caml
> looks awfully bad and there doesn't seem to be any kind of progress
> forward.  I really prefer much more robust, better designed, and
> engineered languages than O'Caml.  With O'Caml you get the worst of
> all world.

Except OCaml brings a considerable user base, who build lots of useful
library bindings, test the compiler and libraries, write tutorials and
books and so forth.

The only solution I can see is to wait until the INRIA team stop making
significant developments (which has arguably already happened) and then
persuade the distro package maintainers to ship a forked OCaml. In many
ways, that would be a great day. On the other hand, if Torben really can
build the foundation of a next generation technical computing platform in
only a few weeks maybe we should do that.

There are far more basic concerns than the one you cite as well. For
example, reading text files without stack overflows is a newbie nightmare.
There are FAQs, of course, but these routines should be in the stdlib (as
they are in .NET) and the basic constructs (like try finally) should be in
the language.

> Trust me, I haven't even nearly exhausted my list of concerning
> problems of social kind with the development of O'Caml or badly
> designed and engineered aspects of the O'Caml language.  And the best
> part is that all of it is true.  Until now, I've just preferred to try
> and be fair.  That is over now.

I find the objections you've cited in this particular post to be entirely
valid concerns. I'm not convinced by some of the other stuff and I believe
the best way forward is to retain compatibility with OCaml to make
migration to a new language easier for OCaml's now substantial user base.
This is partly out of "fear of the unknown". For example, how long would I
have to spend debugging equality issues if I ported the 250kLOC of Smoke to
an SML style? I have no idea...

This is what F# does, of course, but I'd like to see the same language
innovation going on in the open source community. I really believe there is
an awesome opportunity for ML here.

There is one more major concern that we have not mentioned: commerce. I am
more than happy to give away great free software but I think it would be
beneficial for everyone if the next ML made it easy to sell value-add
software (both end user and libraries). Perhaps Java is the best lesson
here (although they screwed the pooch with graphics, which gives us a great
opportunity to leapfrog them).

I'd like to be able to write source code implementing tools for technical
users (scientists and engineers) that has access to a standard API for
OpenGL and GUI (e.g. GTK), compile it to a not-easily-invertible form (like
OCaml bytecode) and sell it so that users can run it on Linux, Mac OS X or
Windows either as libraries to add capabilities to the REPL or as end user
software.

I'm not asking for any fancy security or licensing issues or anything, just
the ability to sell compiled code that runs reliably out of the box. We
tried selling OCaml binaries and ~20% of our customers could not run the
software due to binary incompatibility problems that led to segfaulting.
This is best solved (I believe) by pulling the relevant stuff into the
run-time. Binary compatibility issues are then shifted from the producer
onto the package maintainer who was already solving that problem anyway.

We should probably try to compile a list of features that we would all want
to see in a next generation ML.

Incidentally, what are people's feelings on type classes? Is ad-hoc
polymorphism enough?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/13/2007 5:30:56 PM
On Nov 13, 5:57 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> Going off on a tangent here. OCaml provides physical equality but not
> physical ordering. This boils down to comparing pointers than can be moved
> by the GC. Consequently, to avoid linear searches using physical equality,
> values are sometimes tagged with identities "manually" which, as you say,
> is tedious.
>
> I can think of a couple of "solutions" but they bring their own problems:
>
> . prevent the GC from moving (i.e. no compaction) but this might have
> adverse effects like fragmentation.

To be accurate, moving does not destroy ordering, copying does. But a
generational collector will always be a copying one.

> . tag all values with identities but this sounds like memory-bloating
> overkill.
>
> If a better language existed, how might it solve this problem without
> introducing other problems?

I don't think there is a viable solution. If you allow the program to
obtain and observe specific orderings or hash values this inevitably
will impose severe and costly restrictions on the implementation.

But you can avoid that by moving to a higher level of abstraction: the
reason you want physical orderings or hashes usually is to be able to
construct sets or maps over structured. One solution then is to make
these primitive in the runtime system. We do that in Alice ML, where
there is a built-in low-level map type (('a, 'b) Store.Map.t) that
uses physical hashing on block addresses internally. The garbage
collector is aware of these structures and transparently triggers
suitable rehashing when entries are moved. (For Alice ML, a mechanism
like that was required anyway for concurrent pickling, so it just had
to be exposed to the programmer.)

- Andreas

0
rossberg (600)
11/13/2007 7:46:15 PM
In article <13jjmd3r4ah0o00@corp.supernews.com>,
Jon Harrop  <usenet@jdh30.plus.com> wrote:
> Going off on a tangent here. OCaml provides physical equality but not
> physical ordering.

> I can think of a couple of "solutions" but they bring their own problems:
> 
> . prevent the GC from moving (i.e. no compaction) but this might have
> adverse effects like fragmentation.
> 
> . tag all values with identities but this sounds like memory-bloating
> overkill.
> 
> If a better language existed, how might it solve this problem without
> introducing other problems?

Explicitly tag only those values where the ordering is really required:

http://haskell.org/ghc/docs/latest/html/libraries/base-3.0.0.0/System-Mem-StableName.html

(The integer returned by hashStableName can be used for ordering as
well as for hashing.)


Lauri
0
la (473)
11/13/2007 8:23:12 PM
In article <fhaoou$nfq$1@oravannahka.helsinki.fi>,
Vesa Karvonen  <vesa.karvonen@cs.helsinki.fi> wrote:
> > > sgn :: Int -> Int
> > > sgn x | x > 0   = 1
> > > sgn x | x < 0   = -1
> > > sgn _           = 0
> 
> > Ah, but that is the very worst thing you can do. In the name of
> > satisfying exhaustiveness checking (and perhaps also in the name of
> > efficiency),
> 
> Nope.  The real motivation is neither exhaustiveness checking nor
> efficiency.  The motivation is just to avoid unnecessary verbosity.

Your transformation amounts to removing an assertion check. The
removal certainly makes the code more concise (and more efficient),
but it also means that the precondition for the last clause is no
longer explicitly visible in the code, and also not checked at
run-time. Whether these would be necessary or not is debatable.

> Comparing against zero is redundant here, because there are no
> integers other than 0 that are neither less than nor greater than 0.

Indeed, that's your belief. By removing the guard you have removed
your statement of this belief both from the compiler's and the
reader's eye, and merely tacitly _assumed_ it.

I happen to agree that your belief is correct, but that is beside  the
point: a programmer is fallible, and must take her fallibility into
account in her code.

> I'm talking about your example in particular.  Not some hypothetical
> example.

The purpose of an example is to demonstrate a general argument.
Commonly, the point of refuting an example is to demonstrate a fault
in the general argument that it exemplifies. Hence the refutation
should also be generalizable.

If your refutation of my example is not generalizable, then what
exactly do you intend to achieve with it?

> You could interpret this as saying that your example is
> flawed.

My original point was to demonstrate that a pattern-matching function
can be total even though the exhaustiveness checker cannot prove that
it is. For this my example function was suitable.

You suggested an alternative way of writing the function in a way that
would be accepted by the exhaustiveness checker. I argumented against
that on the grounds that such a transformation is dangerous, even
though in this particular case I believe that the danger doesn't get
actualized.

So I have two arguments: firstly, that a function can be total even
though the compiler cannot prove it, and secondly, that a function can
be _not_ total even though the programmer believes it to be. Clearly,
it is unreasonable to expect a single example to demonstrate both of
these points. :)

Let's try again, with a slight variation. Let's write a function:

sgn :: Double -> Double
sgn x |  x < 0  = -1
sgn x | x == 0  =  0
sgn x |  x > 0  =  1

Now, for the moment, let us suspect that this function might be total
but, as we are all fallible, we might be wrong. The compiler, also, is
at its wits' end: it cannot know if the guards are exhaustive, and can
only conservatively assume that they are not.

Let's consider a language with enforced exhaustiveness checking. In
this case, the programmer must add a final default clause to satisfy
the compiler:

sgn _           = error "impossible!"

Suppose the function actually is total. In this case, the last clause
is never reached, and the exhaustiveness checking forced us to write
dead code. This is a bad outcome, let's give it an arbitrary valuation
of -1.

Then suppose the function is not total. This means that the
exhaustiveness checker forced us to add a piece of code that will
actually detect an error in our code and assumptions when an
unexpected value is received as an argument. This is a good thing,
let's give this outcome a valuation of +1.


Then consider the altenative formulation that you suggested:

sgn :: Double -> Double
sgn x |  x < 0  = -1
sgn x |  x > 0  =  1
sgn _           =  0

This passes the exhaustiveness checker without problems.

Suppose that the function is actually total. Then the exhaustiveness
checker neither hindered nor helped. Let's give this outcome a
valuation of 0.

Then suppose that the function is not total. Then an unexpected value
is not detected, and operation is continued silently, and the function
returns 0 even though that is only a valid result for argument 0, not
for the unexpected value. This is a disaster, let's value it -10.

Then consider a language without exhaustiveness checking (or with
exhaustiveness checking that is only used internally for optimization
purposes). Let's return to the first example:

sgn :: Double -> Double
sgn x |  x < 0  = -1
sgn x | x == 0  =  0
sgn x |  x > 0  =  1

Suppose the function is total. Then the lack of exhaustiveness
checking neither helped nor hindered, so we value this outcome as 0.

Then suppose the function is not total. Then, if an unexpected value
is encountered, a run-time error is raised. However, this time it is
done automatically, and we need not write an explicit clause that does
the same thing. I feel this a superior outcome, with a valuation of 2.

So here's a summary of the valuations:

              checking     alternate version     no checking
total           -1                  0                0
not total        1                -10                2

Now, since the information about the totality of the function is
unavailable to us statically (since both the compiler and the
programmer are too stupid), we must choose our coding style based on
the expected (or perhaps worst) valuation of the style in different
situations. Here it seems clear that the unchecked style is the best:
it requires the least extra code, and detects no less errors than any
of the other solutions.


My argument here is only that there are situations where the unchecked
style is better. There are also situations where checking yields real
benefit: those are the ones where the function is not total, and the
exhaustiveness checker can actually give us a shape that can be passed
to the function yet is not matched by any of the clauses. The final
valuation of the different styles depends on how much weight must be
given to each of these different situations. I'm only saying that the
answer is not obvious.

> > you have transformed your program in a way whose
> > semantics-preservedness depends on your belief that the clauses
> > actually are exhaustive, and after the transformation this property
> > is no longer checked!
> 
> It wasn't checked statically earlier either.

But it was dynamically checked.

> If this was a pacemaker, the patient would have died anyway as soon as
> the "impossible happened" (in GHC parlance :-).

If it were a pacemaker, then "when the impossible happened" there
would be a loud warning signal notifying everyone that the pacemaker
was malfunctioning. This might be noticed early enough to fix the
problem while the patient was still alive.

The -10 outcome, the danger in the style of solution you were
proposing, would mean that the pacemaker was silently operating subtly
erroneously, and would eventually kill the patient without anyone
seeing what was going on until it was too late.

And, of course, in my latter example there _is_ an unexpected value:

module ExhTest where

sgn :: Double -> Double
sgn x |  x < 0  = -1
sgn x | x == 0  =  0
sgn x |  x > 0  =  1

sgn2 :: Double -> Double
sgn2 x |  x < 0  = -1
sgn2 x |  x > 0  =  1
sgn2 _           =  0

*ExhTest> sgn (0 / 0)
*** Exception: ExhTest.hs:(4,0)-(6,19): 
    Non-exhaustive patterns in function sgn

*ExhTest> sgn2 (0 / 0)
0.0


Lauri
0
la (473)
11/13/2007 10:48:25 PM
rossberg@ps.uni-sb.de writes:
> On Nov 13, 5:57 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
> > Going off on a tangent here. OCaml provides physical equality but not
> > physical ordering. This boils down to comparing pointers than can be moved
> > by the GC. Consequently, to avoid linear searches using physical equality,
> > values are sometimes tagged with identities "manually" which, as you say,
> > is tedious.
> >
> > I can think of a couple of "solutions" but they bring their own problems:
> >
> > . prevent the GC from moving (i.e. no compaction) but this might have
> > adverse effects like fragmentation.
> 
> To be accurate, moving does not destroy ordering, copying does. But a
> generational collector will always be a copying one.

The latter claim is obviously not true (non-copying generational gcs
exist). But the first point is quite valid: a mark-sweep-compacting gc
will retain the order of the objects when they're moved, so pointer
less-than comparisons would be stable.
 
> > . tag all values with identities but this sounds like memory-bloating
> > overkill.
> >
> > If a better language existed, how might it solve this problem without
> > introducing other problems?
> 
> I don't think there is a viable solution. If you allow the program to
> obtain and observe specific orderings or hash values this inevitably
> will impose severe and costly restrictions on the implementation.

One provably viable solution is to have a default object
representation that does not store a identity as a part of the value
and another representation that does. When an object's identity is
taken for the first time have the implementation transparently switch
the object to the second representation.

-- 
Juho Snellman
0
jsnell (317)
11/14/2007 12:56:50 AM
Jon Harrop <usenet@jdh30.plus.com> writes:


> The only solution I can see is to wait until the INRIA team stop making
> significant developments (which has arguably already happened) and then
> persuade the distro package maintainers to ship a forked OCaml. In many
> ways, that would be a great day. On the other hand, if Torben really can
> build the foundation of a next generation technical computing platform in
> only a few weeks maybe we should do that.

I said I could write a non-optimising compiler for core SML in a few
weeks, which is not quite the same.  And it really says more about the
simplicity of core SML than it does about my abilities as a compiler
writer.

> We should probably try to compile a list of features that we would all want
> to see in a next generation ML.
>
> Incidentally, what are people's feelings on type classes? Is ad-hoc
> polymorphism enough?

I like Haskell type classes, though some of the experimental features
may be a little OTT (I would like the next generation ML to be
relatively simple).  With type classes, the module system might be
simplified -- or you could integrate type classes and modules.  I
think the latter requires some research, though.

There are lots of minor details regarding syntax etc. that I would
like in a future ML, but some of the more fundamental changes I would
like to see are:

 - Concurrency.

 - Linear types so you can, e.g., linearly type file handles to ensure
   deterministic access order even in the presence of concurrency.

 - A type-and-effect system so effects are visible in type but can be
   delimited.  Linearly typed file access can easily be delimited: It
   only affects the file handle, which is consumed and a new one
   produced, so you can treat the new file handle as a modified
   "world".

	Torben
0
torbenm5 (42)
11/14/2007 8:52:00 AM
Lauri Alanko <la@iki.fi> wrote:
> Vesa Karvonen  <vesa.karvonen@cs.helsinki.fi> wrote:
[...]
> >   %Constructor
> > 
> > and, in the case of an unary constructor, get the function
> > 
> >   fn Constructor x => SOME x | _ => NONE

> Looks like an extractor. :)

Ok.  I read your blurb about extractors in Scala.  What I'm proposing
here is much simpler, involves no implicit conversion, and doesn't
really extend pattern matching.  What I'm proposing is just a natural
dual to the derived form (syntactic sugar) for record selectors in
SML.  In SML, records are not accessed using the typical dot syntax
"r.x", but rather using selector functions "#x r".  Writing # lab in
SML is equivalent to writing

  fn {lab = vid, ...} => vid

which is a first-class function for extracting the lab -field from a
given record with that field.  This derived form is given on page 56
of the Definition of Standard ML.  What I'm proposing here is a dual
of that derived form for variant types.

-Vesa Karvonen
0
11/14/2007 10:27:34 AM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> The only solution I can see is to wait until the INRIA team stop making
>> significant developments (which has arguably already happened) and then
>> persuade the distro package maintainers to ship a forked OCaml. In many
>> ways, that would be a great day. On the other hand, if Torben really can
>> build the foundation of a next generation technical computing platform in
>> only a few weeks maybe we should do that.
> 
> I said I could write a non-optimising compiler for core SML in a few
> weeks, which is not quite the same.

On the contrary, I think that could be the perfect start. Here's my first
guess at the evolution of a new language (suitable for technical
computing):

The language would need some extra features beyond core SML and the
implementation would need a REPL and an FFI. The FFI would require some
specialized types to be exposed (e.g. arrays of complex numbers) in order
to facilitate high-performance interop with libraries like FFTW.

Then other people can bind libraries like GTK and OpenGL. Then write a
simple IDE that lets people develop programs and spawn visualizations. Then
create packages for major distros and start accumulating users.

Then add bindings to FFTW, LAPACK, databases and networking libraries.

This platform is completely free and open source but it enables authors to
sell libraries to users of the platform that extend its functionality
without having to worry about binary compatibility issues and
cross-platform compilation.

If enough people pulled together, I'm sure this could get off the ground in
under 1 year. Provided a goal of the project is to build a platform
suitable for commerce, I would be more than happy to contribute to the
OpenGL bindings, visualization (e.g. GUI), stdlib and documentation.

> And it really says more about the 
> simplicity of core SML than it does about my abilities as a compiler
> writer.

As I see it, such a project only requires commitment and the only thing
blocking commitment is consensus. Specifically, what features go into this
language?

>> Incidentally, what are people's feelings on type classes? Is ad-hoc
>> polymorphism enough?
> 
> I like Haskell type classes, though some of the experimental features
> may be a little OTT (I would like the next generation ML to be
> relatively simple).  With type classes, the module system might be
> simplified -- or you could integrate type classes and modules.  I
> think the latter requires some research, though.

Ok. So type classes and a functor-free module system is both feasible to
write and useful for users? That would be more than satisfactory for my
purposes.

> There are lots of minor details regarding syntax etc. that I would
> like in a future ML, but some of the more fundamental changes I would
> like to see are:
> 
>  - Concurrency.

Ugh! I agree that concurrency is important but which of the many approaches
is best?

>  - Linear types so you can, e.g., linearly type file handles to ensure
>    deterministic access order even in the presence of concurrency.

Absolutely.

>  - A type-and-effect system so effects are visible in type but can be
>    delimited.  Linearly typed file access can easily be delimited: It
>    only affects the file handle, which is consumed and a new one
>    produced, so you can treat the new file handle as a modified
>    "world".

I would like:

.. A lot more pattern matching than SML: guarded patterns, or-patterns, array
literals, strings, forcing lazy values. I would at least like more linear
patterns (e.g. matching any string beginning with "#", and array beginning
with zero) but am also interested in some non-linear ones (e.g. regexps and
extracting elements from sets).

.. Polymorphic variants (or something offering the same functionality as the
use of polymorphic variants in LablGL).

.. Complex numbers (and literals) as built-in types with an unboxed
representation.

.. Overloading of operators (+, - etc.), casts (just "float" rather
than "float_of_int", "float_of_int64" etc.) and indexing (just "map.[key]"
as F# has instead of "array.(index)", "string.[index]" and "Hashtbl.find
map key" as OCaml has).

.. Labelled and optional arguments (perhaps this could be SML style with some
syntactic sugar rather than OCaml style?).

.. Array literals.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/14/2007 11:07:30 AM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Torben �gidius Mogensen wrote:
>> Jon Harrop <usenet@jdh30.plus.com> writes:
>>> The only solution I can see is to wait until the INRIA team stop making
>>> significant developments (which has arguably already happened) and then
>>> persuade the distro package maintainers to ship a forked OCaml. In many
>>> ways, that would be a great day. On the other hand, if Torben really can
>>> build the foundation of a next generation technical computing platform in
>>> only a few weeks maybe we should do that.
>> 
>> I said I could write a non-optimising compiler for core SML in a few
>> weeks, which is not quite the same.
>
> On the contrary, I think that could be the perfect start.

Why?  There are already a dozen or so independent implementations of
core SML around.  It is better to make a solid design first, and then
start implementing.

> As I see it, such a project only requires commitment and the only thing
> blocking commitment is consensus. Specifically, what features go into this
> language?
>
>>> Incidentally, what are people's feelings on type classes? Is ad-hoc
>>> polymorphism enough?
>> 
>> I like Haskell type classes, though some of the experimental features
>> may be a little OTT (I would like the next generation ML to be
>> relatively simple).  With type classes, the module system might be
>> simplified -- or you could integrate type classes and modules.  I
>> think the latter requires some research, though.
>
> Ok. So type classes and a functor-free module system is both feasible to
> write and useful for users? That would be more than satisfactory for my
> purposes.

Why functor-free?

>> There are lots of minor details regarding syntax etc. that I would
>> like in a future ML, but some of the more fundamental changes I would
>> like to see are:
>> 
>>  - Concurrency.
>
> Ugh! I agree that concurrency is important but which of the many approaches
> is best?

I can't really say.  There are lots of people whow a lot more about
concurrency than I do.

> I would like:
>
> . A lot more pattern matching than SML: guarded patterns, or-patterns, array
> literals, strings, forcing lazy values. I would at least like more linear
> patterns (e.g. matching any string beginning with "#", and array beginning
> with zero) but am also interested in some non-linear ones (e.g. regexps and
> extracting elements from sets).

These are all minor details, possibly with the exception of allowing
non-linear patterns or nondeterministic matching.

> . Polymorphic variants (or something offering the same functionality as the
> use of polymorphic variants in LablGL).
>
> . Complex numbers (and literals) as built-in types with an unboxed
> representation.

I think it is better to let decisions of boxed/unboxed values be up to
the implementation.

> . Overloading of operators (+, - etc.),

If type classes are added, these should be used for overloading.

> . Labelled and optional arguments (perhaps this could be SML style with some
> syntactic sugar rather than OCaml style?).
>
> . Array literals.

Is [1,2,3] a literal or an expression that evaluates to a list?  Does
it matter?  In the same way, what is important is a concise way to
build arrays rather than whether these represent literals or
expressions.  The latter would allow variables to occur in builders,
similar to [1,2,x] in list builders.  Actually, the list notation can
be overloaded, so [1,2,3] can be either a list of three elements, a
vector of three elements, an array of three elements or other.  Type
classes can handle this by translating [1,2,3] to Cons 1 (Cons 2 (Cons
3 Nil))) and then overload Cons and Nil.  Whether the building happens
at compile-time, run-time or other is mainly a matter of optimisation,
except if you build mutable structures (are they shared or not?).

	Torben
0
torbenm5 (42)
11/14/2007 11:38:40 AM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> Torben �gidius Mogensen wrote:
>>> I said I could write a non-optimising compiler for core SML in a few
>>> weeks, which is not quite the same.
>>
>> On the contrary, I think that could be the perfect start.
> 
> Why?  There are already a dozen or so independent implementations of
> core SML around.  It is better to make a solid design first, and then
> start implementing.

Do you mean take an existing SML implementation and fork it in order to add
the language features I'm describing? If so, which implementations might be
most suitable?

My impression is that all current SML implementations were designed and
built as tools for programming language research. To the best of my
knowledge, none of the authors have any interest in selling their
implementations to a wider audience. I think this is a great shame because
a closely related language would be ideal for technical computing and would
garner huge interest from scientists and engineers. This is exactly the
market being targetted by Microsoft with F# but no equivalent innovation is
going on in the open source community.

Incidentally, Gambas BASIC provides a good lesson in terms of sales:

  http://gambas.sourceforge.net/

Despite being an unamazing language it has garnered more users than Haskell
and OCaml in only three years. I believe the reason is simply its list of
features:

.. OpenGL
.. GTK and Qt GUI programming
.. Networking
.. MySQL, PostgreSQL, Firebird, ODCB and SQLite databases
.. CGI web applications

>>> I like Haskell type classes, though some of the experimental features
>>> may be a little OTT (I would like the next generation ML to be
>>> relatively simple).  With type classes, the module system might be
>>> simplified -- or you could integrate type classes and modules.  I
>>> think the latter requires some research, though.
>>
>> Ok. So type classes and a functor-free module system is both feasible to
>> write and useful for users? That would be more than satisfactory for my
>> purposes.
> 
> Why functor-free?

I assumed that was what you meant by "simplified module system". What were
you thinking of?

>>>  - Concurrency.
>>
>> Ugh! I agree that concurrency is important but which of the many
>> approaches is best?
> 
> I can't really say.  There are lots of people whow a lot more about
> concurrency than I do.

Ok. I agree concurrency is important but I'm not sure which approach to
prefer. I wouldn't even mind if it didn't run under Windows, e.g. was Unix
fork based.

>> I would like:
>>
>> . A lot more pattern matching than SML: guarded patterns, or-patterns,
>> array literals, strings, forcing lazy values. I would at least like more
>> linear patterns (e.g. matching any string beginning with "#", and array
>> beginning with zero) but am also interested in some non-linear ones (e.g.
>> regexps and extracting elements from sets).
> 
> These are all minor details, possibly with the exception of allowing
> non-linear patterns or nondeterministic matching.

Does pattern matching over lazy values count as non-linear?

>> . Polymorphic variants (or something offering the same functionality as
>> the use of polymorphic variants in LablGL).
>>
>> . Complex numbers (and literals) as built-in types with an unboxed
>> representation.
> 
> I think it is better to let decisions of boxed/unboxed values be up to
> the implementation.

I think an efficient FFI for complex arrays would be very useful and that
imposes some requirements on the implementation, like unboxed complex
arrays. This is true in F# and the only overhead in the FFI is then pinning
the array so the GC can't move it while an external library manipulates it.

Also, OpenGL interop would benefit from the ability to store vertex data
unboxed in a vertex array. That means unboxing more general data structures
equivalent to a C struct containing bytes, shorts, ints, floats and so on.
You can do this in F# by declaring a struct rather than a class.

>> . Overloading of operators (+, - etc.),
> 
> If type classes are added, these should be used for overloading.

Yes.

>> . Labelled and optional arguments (perhaps this could be SML style with
>> some syntactic sugar rather than OCaml style?).
>>
>> . Array literals.
> 
> Is [1,2,3] a literal or an expression that evaluates to a list?  Does
> it matter?

I think it is important to be able to construct and deconstruct arrays
easily.

> In the same way, what is important is a concise way to 
> build arrays rather than whether these represent literals or
> expressions.  The latter would allow variables to occur in builders,
> similar to [1,2,x] in list builders.

My mistake. That's what I meant.

> Actually, the list notation can 
> be overloaded, so [1,2,3] can be either a list of three elements, a
> vector of three elements, an array of three elements or other. Type 
> classes can handle this by translating [1,2,3] to Cons 1 (Cons 2 (Cons
> 3 Nil))) and then overload Cons and Nil.

Interesting. So you would write a type annotation rather than using
different syntaxes or constructors, like this:

  list:   [1,2,3]
  array:  ([1,2,3]) : int array)
  set:    ([1,2,3]) : int set)

and so on. Then you can have one type annotation for a variety of
expressions/patterns:

  match x : _ array with
  | [] -> 0
  | [_, n] -> n
  | _ -> raise Not_found

Any thoughts on OCaml's semicolon separator and getting rid of as many
brackets as possible?

Also, what about replacing the built-in list data structure with something
else like a rope?

> Whether the building happens 
> at compile-time, run-time or other is mainly a matter of optimisation,
> except if you build mutable structures (are they shared or not?).

Yes. No sharing for mutable data structures. Immutable could be shared
automatically later as an optimization.

As Vesa said, OCaml's sharing of mutable strings is not nice. The
justification given was "performance" but I don't buy that.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/14/2007 10:41:22 PM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Torben �gidius Mogensen wrote:
>> Jon Harrop <usenet@jdh30.plus.com> writes:
>>> Torben �gidius Mogensen wrote:
>>>> I said I could write a non-optimising compiler for core SML in a few
>>>> weeks, which is not quite the same.
>>>
>>> On the contrary, I think that could be the perfect start.
>> 
>> Why?  There are already a dozen or so independent implementations of
>> core SML around.  It is better to make a solid design first, and then
>> start implementing.
>
> Do you mean take an existing SML implementation and fork it in order to add
> the language features I'm describing? If so, which implementations might be
> most suitable?

If you want to start from core SML and add features, you could start
from any of the existing implementations, an dthere would be no point
in making a new.  If you want to design a new language inspired by
SML, you might as well start from scratch, but you need a design befor
eyou start imlementing.

> My impression is that all current SML implementations were designed and
> built as tools for programming language research.

Harlekin ML was built as a commercial implementation of SML, but you
probably can't call that "current".

> To the best of my knowledge, none of the authors have any interest
> in selling their implementations to a wider audience.

I don't think this is true, though.

> I think this is a great shame because
> a closely related language would be ideal for technical computing and would
> garner huge interest from scientists and engineers. This is exactly the
> market being targetted by Microsoft with F# but no equivalent innovation is
> going on in the open source community.

There are various "successor ML" projects underway.

>>>> I like Haskell type classes, though some of the experimental features
>>>> may be a little OTT (I would like the next generation ML to be
>>>> relatively simple).  With type classes, the module system might be
>>>> simplified -- or you could integrate type classes and modules.  I
>>>> think the latter requires some research, though.
>>>
>>> Ok. So type classes and a functor-free module system is both feasible to
>>> write and useful for users? That would be more than satisfactory for my
>>> purposes.
>> 
>> Why functor-free?
>
> I assumed that was what you meant by "simplified module system". What were
> you thinking of?

I was thinking that some of the overlap with type classes might be
reduced.  Functors are not really overlapping type classes, so I see
no reason to take these away.

>>> I would like:
>>>
>>> . A lot more pattern matching than SML: guarded patterns, or-patterns,
>>> array literals, strings, forcing lazy values. I would at least like more
>>> linear patterns (e.g. matching any string beginning with "#", and array
>>> beginning with zero) but am also interested in some non-linear ones (e.g.
>>> regexps and extracting elements from sets).
>> 
>> These are all minor details, possibly with the exception of allowing
>> non-linear patterns or nondeterministic matching.
>
> Does pattern matching over lazy values count as non-linear?

Not really, no.

>>> . Complex numbers (and literals) as built-in types with an unboxed
>>> representation.
>> 
>> I think it is better to let decisions of boxed/unboxed values be up to
>> the implementation.
>
> I think an efficient FFI for complex arrays would be very useful and that
> imposes some requirements on the implementation, like unboxed complex
> arrays. This is true in F# and the only overhead in the FFI is then pinning
> the array so the GC can't move it while an external library manipulates it.

O.K., that makes sense.

> Also, OpenGL interop would benefit from the ability to store vertex data
> unboxed in a vertex array. That means unboxing more general data structures
> equivalent to a C struct containing bytes, shorts, ints, floats and so on.
> You can do this in F# by declaring a struct rather than a class.

Same as C#, then.

>> Actually, the list notation can 
>> be overloaded, so [1,2,3] can be either a list of three elements, a
>> vector of three elements, an array of three elements or other. Type 
>> classes can handle this by translating [1,2,3] to Cons 1 (Cons 2 (Cons
>> 3 Nil))) and then overload Cons and Nil.
>
> Interesting. So you would write a type annotation rather than using
> different syntaxes or constructors, like this:
>
>   list:   [1,2,3]
>   array:  ([1,2,3]) : int array)
>   set:    ([1,2,3]) : int set)
>
> and so on.

Exactly.

> Any thoughts on OCaml's semicolon separator and getting rid of as many
> brackets as possible?

This is a bit tricky.  I'm not terribly fond of Haskell's
layout-sensitive syntax, but it is better than having to write a lot
of parentheses all over the place.  I prefer writing

  case e of
    p1 => e1
  | p2 => e2
  end

instead of

  (case e of
     p1 => e1
   | p2 => e2
  )

I.e., explicit terminating keywords rather than brackets around
variable-sized expressions.  But if you could make it optional, that
would be best: "end" matches the closest open "let", "case", etc., but
you don't have to write it unless necessary.

> Also, what about replacing the built-in list data structure with something
> else like a rope?

I'm not sure what you mean by "rope" here.

	Torben
0
torbenm5 (42)
11/15/2007 10:13:18 AM
In article <7zy7cz24w1.fsf@app-4.diku.dk>,
 torbenm@app-4.diku.dk (Torben �gidius Mogensen) wrote:

> Jon Harrop <usenet@jdh30.plus.com> writes:
.... 
> > Any thoughts on OCaml's semicolon separator and getting rid of as many
> > brackets as possible?
> 
> This is a bit tricky.  I'm not terribly fond of Haskell's
> layout-sensitive syntax, but it is better than having to write a lot
> of parentheses all over the place.  I prefer writing
> 
>   case e of
>     p1 => e1
>   | p2 => e2
>   end
> 
> instead of
> 
>   (case e of
>      p1 => e1
>    | p2 => e2
>   )
> 
> I.e., explicit terminating keywords rather than brackets around
> variable-sized expressions.  But if you could make it optional, that
> would be best: "end" matches the closest open "let", "case", etc., but
> you don't have to write it unless necessary.

If I remember right, the problem with Objective CAML is block
structure implied by separators - asking for trouble.

   let ... = begin
       match ... with
          ... -> begin ... end
          ... -> begin ... end ;  where am I?
       end

   Donn Cave, donn@u.washington.edu
0
Donn
11/15/2007 7:00:06 PM
Donn Cave <donn@u.washington.edu> wrote:
[...]
> If I remember right, the problem with Objective CAML is block
> structure implied by separators - asking for trouble.

>    let ... = begin
>        match ... with
>           ... -> begin ... end
>           ... -> begin ... end ;  where am I?
>        end

I agree.  I recall that I also got bitten by this aspect of O'Caml's
syntax.  When an imperative function grows longer than few lines, it
becomes an unreadable mess in O'Caml, and that happens often, because
in O'Caml, you have to use imperative constructs (loops, mutable
fields, assignment, mutable strings and arrays, ...) to get reasonable
performance, and performance is everything in O'Caml.  Furthermore,
this is far from the only confusing aspect of O'Caml's syntax.  What
happened to that guy who tried to revise O'Caml's syntax?  (I've got a
nasty true story about this, but most unfortunately I cannot prove it,
so I'll refrain from telling it, because I no longer have e-mails that
I received while working at Housemarque in 2002.  It is theoretically
possible that one of my former colleagues could verify the story, but
I doubt that he remembers.)  Nevertheless, it is interesting to
observe that CamlP4 was recently "revised".  What I've actually heard
first-hand from a couple of guys who are using CamlP4, is that it
didn't really improve things.  My guess is that the reasons for
revising CamlP4 were mostly political.  It seems that nobody can save
O'Caml.  Doom awaits those who go with O'Caml.

-Vesa Karvonen
0
11/15/2007 7:52:17 PM
Donn Cave wrote:
> If I remember right, the problem with Objective CAML is block
> structure implied by separators - asking for trouble.
> 
>    let ... = begin
>        match ... with
>           ... -> begin ... end
>           ... -> begin ... end ;  where am I?
>        end

Just hit C-C C-Q in Emacs to see where you are.

My preference for a non-whitespace sensitive syntax is probably either "end"
after "match" but not after "function" (these are rarely nested) and not
after "if":

  let is_sign n = match n with
    | -1 | 0 | 1 -> true
    | _ -> false
    end

  let is_sign = function
    | -1 | 0 | 1 -> true
    | _ -> false

  if p then t else f

The alternative is to follow F#'s whitespace sensitive syntax which has its
merits but obviates automatic code indentation and often screws up the
semantics of code that you cut and paste (my pet hatred about Haskell). The
main benefit is that removing "in" makes nested "let" bindings look just
like top-level definitions, so you can evaluate them (as a block with
ALT+ENTER or a line at a time with ALT+' in Visual Studio) without having
to fiddle around.

As OCaml has shown: automatic indentation and real-time type throwback are
absolutely essential features. In fact, this is a much more important
point: to be useful this language implementation must have a good IDE.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/15/2007 9:30:16 PM
Jon:
[...]
> As OCaml has shown: automatic indentation and real-time type throwback are
> absolutely essential features. In fact, this is a much more important
> point: to be useful this language implementation must have a good IDE.

Yeah, that is what people say about Java.  I could probably dig up
dozens of posts much like yours from LtU, for example.  There is this
guy there, much like you, basically just regularly advertising his
business there in disguise ("full disclosure" and all that).  Except
that the product is for Java rather than O'Caml.  He is always eagerly
telling you there how the IDE will do this and that in the next N
months, you know, how genuine problems in the language are covered up
with IDE makeup.  Perhaps your real message is that the O'Caml
language tastes bitter and undeveloped, so you have to smooth it up
with an IDE full of sugar.  But too much sugar just makes you fat and
ruins your teeth.

-Vesa Karvonen

P.S. Jon, I haven't had this much fun in a long time!  Thank you for
showing the way!
0
11/15/2007 11:05:40 PM
Vesa Karvonen wrote:

> didn't really improve things.  My guess is that the reasons for
> revising CamlP4 were mostly political.  It seems that nobody can save
> O'Caml.  Doom awaits those who go with O'Caml.

Wow. You certainly have nothing to learn in the sweeping
generalizations department from certain persons you oppose.

- M
0
11/15/2007 11:20:24 PM
Jon:
[...]
> talking to yourself on the MLKit developers list, yes.

Since you brought this up, I've actually gotten infinitely more
support from MLKit's developer(s) than I ever got from any or all of
O'Caml's developers (zero, 0, none, nada).  See here for a proof:

  http://mlkit.svn.sourceforge.net/viewvc/*checkout*/mlkit/trunk/kit/NEWS .

(The other part of the proof is in O'Caml's mailing list archives.)

Let's imagine for a moment.  If I were reporting bugs/issues like this
in O'Caml on the O'Caml mailing list, I'd probably get public replies
from a couple of guys who noticed the same issues and submitted
patches to fix them "three years ago".  Heck, I'd probably also get a
couple of e-mails privately telling me how they agree with me, but
revising things in the language is considered waste of time.  You
know, the definition of O'Caml is the pretty in the source code --- in
Star Wars style.  So, technically, whatever it does is correct and
there is no point in "fixing" it.  Anyway, years later, taking a brief
look at O'Caml, I would find out that the same problem still exists
and hasn't been fixed.  This even despite the fact that it has been
reported *and* fixed independently by several users.  Hey, wait a
moment...  That is what actually happened!  It is a true story.  No
imagination needed.  The future of O'Caml looks bad.  It is worse than
failure.

-Vesa Karvonen
0
11/15/2007 11:25:56 PM
In article <13jpf4791ivje23@corp.supernews.com>,
 Jon Harrop <usenet@jdh30.plus.com> wrote:

> Donn Cave wrote:
> > If I remember right, the problem with Objective CAML is block
> > structure implied by separators - asking for trouble.
> > 
> >    let ... = begin
> >        match ... with
> >           ... -> begin ... end
> >           ... -> begin ... end ;  where am I?
> >        end
> 
> Just hit C-C C-Q in Emacs to see where you are.

I know where I am - I am not in Emacs, but then I am not in
Objective CAML either.

Your advice is probably useful for those who are forced by
circumstances to use such a language, but if we were talking
about syntax choices, separator-implied block structure is
not a good one, was my point.

   Donn Cave, donn@u.washington.edu
0
Donn
11/16/2007 12:17:58 AM
Donn Cave wrote:
> In article <13jpf4791ivje23@corp.supernews.com>,
>  Jon Harrop <usenet@jdh30.plus.com> wrote:
>> Donn Cave wrote:
>> > If I remember right, the problem with Objective CAML is block
>> > structure implied by separators - asking for trouble.
>> > 
>> >    let ... = begin
>> >        match ... with
>> >           ... -> begin ... end
>> >           ... -> begin ... end ;  where am I?
>> >        end
>> 
>> Just hit C-C C-Q in Emacs to see where you are.
> 
> I know where I am - I am not in Emacs, but then I am not in
> Objective CAML either.
> 
> Your advice is probably useful for those who are forced by
> circumstances to use such a language, but if we were talking
> about syntax choices, separator-implied block structure is
> not a good one, was my point.

Are you advocating that new languages be designed for use without IDEs?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/16/2007 9:32:56 AM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> Do you mean take an existing SML implementation and fork it in order to
>> add the language features I'm describing? If so, which implementations
>> might be most suitable?
> 
> If you want to start from core SML and add features, you could start
> from any of the existing implementations, an dthere would be no point
> in making a new.  If you want to design a new language inspired by
> SML, you might as well start from scratch, but you need a design befor
> eyou start imlementing.

Many of the features I'd like are already in OCaml and the rest should be
sufficiently trivial that a design isn't necessary (e.g. try finally,
better stdlib).

>> To the best of my knowledge, none of the authors have any interest
>> in selling their implementations to a wider audience.
> 
> I don't think this is true, though.

Who do you think might be interested in building an open source technical
computing platform based upon ML?

>> I think this is a great shame because
>> a closely related language would be ideal for technical computing and
>> would garner huge interest from scientists and engineers. This is exactly
>> the market being targetted by Microsoft with F# but no equivalent
>> innovation is going on in the open source community.
> 
> There are various "successor ML" projects underway.

Do you have any references for them? Do they aspire to garner users?

>> I assumed that was what you meant by "simplified module system". What
>> were you thinking of?
> 
> I was thinking that some of the overlap with type classes might be
> reduced.  Functors are not really overlapping type classes, so I see
> no reason to take these away.

Ok.

>> Does pattern matching over lazy values count as non-linear?
> 
> Not really, no.

Excellent. Would there be much objection to supporting that?

>> Also, OpenGL interop would benefit from the ability to store vertex data
>> unboxed in a vertex array. That means unboxing more general data
>> structures equivalent to a C struct containing bytes, shorts, ints,
>> floats and so on. You can do this in F# by declaring a struct rather than
>> a class.
> 
> Same as C#, then.

Probably, yes.

>> Any thoughts on OCaml's semicolon separator and getting rid of as many
>> brackets as possible?
> 
> This is a bit tricky.  I'm not terribly fond of Haskell's
> layout-sensitive syntax,

Agreed.

> but it is better than having to write a lot of parentheses all over the
> place.  I prefer writing 
> 
>   case e of
>     p1 => e1
>   | p2 => e2
>   end
> 
> instead of
> 
>   (case e of
>      p1 => e1
>    | p2 => e2
>   )

Yes.

> I.e., explicit terminating keywords rather than brackets around
> variable-sized expressions.  But if you could make it optional, that
> would be best: "end" matches the closest open "let", "case", etc., but
> you don't have to write it unless necessary.

As long as they're optional, that's fine by me. I don't want "end" after
every pattern match.

What about non-recursive type definitions so types can be superceded?

  type t = ..
  type rec t = ..

>> Also, what about replacing the built-in list data structure with
>> something else like a rope?
> 
> I'm not sure what you mean by "rope" here.

A balanced binary tree:

  http://eigenclass.org/repos/oropes/head/rope.ml

Offers much faster indexing, subsequence, appending and so forth in exchange
for slightly slower prepend and decapitate. It would be a better general
purpose sequence container than a singly linked list.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/16/2007 9:51:59 AM
In article <7zy7cz24w1.fsf@app-4.diku.dk>,
Torben �gidius Mogensen <torbenm@app-4.diku.dk> wrote:
> I was thinking that some of the overlap with type classes might be
> reduced.  Functors are not really overlapping type classes, so I see
> no reason to take these away.

I don't quite see how functors would be special. Signatures correspond
to type classes, modules to class instances, and functors to
qualified, polymorphic class instances. For instance, where the SML/NJ
library has:

functor BinarySetFn (ORD_KEY) : ORD_SET

then Haskell's Edison library has:

instance Ord a => C.OrdSet (Set a) a

I'd say this is pretty much overlapping.


Lauri
0
la (473)
11/16/2007 11:04:48 AM
Markus E L <development-2006-8ecbb5cc8aREMOVETHIS@andthatm-e-leypold.de> wrote:
[...]
> Wow.

Thanks!  I've succeeded at least partially.

> You certainly have nothing to learn in the sweeping generalizations
> department from certain persons you oppose.

Not quite.  I'm just a poor imitation of the best.  You see, I've been
just using phrases, either almost literally, or just in meaning, from
a certain person we both recognize by name as well as nickname.
Anyone can easily make their own mind about this by reading the
archives and I fully encourage that.  What I'm most vigorously
opposing, of course, is FUD (Fear, Uncertainty, and Doubt) [1].  In my
opinion, FUD should not be accepted in a technical / scientific forum
like this.  It strikes me as hugely disappointing to see several
people defending certain person's blatant FUD on several technical
forums.  You know, being nice in one forum doesn't make up for being a
pest in all others.  At any rate, effective anti-war movies may still
be war movies [2].  And, no doubt, the best anti-war movies, whether
satirical or just realistic, are based on true events, just like my
anti-FUD posts on this thread.

BTW, weren't you supposed to put me in your killfile?

-Vesa Karvonen

[1] http://en.wikipedia.org/wiki/Fear%2C_uncertainty_and_doubt
[2] http://en.wikipedia.org/wiki/Anti-war_film
0
11/16/2007 12:13:58 PM
On Nov 16, 12:04 pm, Lauri Alanko <l...@iki.fi> wrote:
> In article <7zy7cz24w1....@app-4.diku.dk>,
> Torben =C6gidius Mogensen <torb...@app-4.diku.dk> wrote:
>
> > I was thinking that some of the overlap with type classes might be
> > reduced.  Functors are not really overlapping type classes, so I see
> > no reason to take these away.
>
> I don't quite see how functors would be special. Signatures correspond
> to type classes, modules to class instances, and functors to
> qualified, polymorphic class instances. For instance, where the SML/NJ
> library has:
>
> functor BinarySetFn (ORD_KEY) : ORD_SET
>
> then Haskell's Edison library has:
>
> instance Ord a =3D> C.OrdSet (Set a) a
>
> I'd say this is pretty much overlapping.

Indeed. More generally, type classes are basically a subset of ML
structures and functors, but with the (huge) added value of automatic
inference. Fortunately, there recently has been some progress on
unifying the two mechanisms, so that there is hope to see them both
peacefully coexist in one language some time.

- Andreas

0
rossberg (600)
11/16/2007 3:08:19 PM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Torben �gidius Mogensen wrote:

>> There are various "successor ML" projects underway.
>
> Do you have any references for them? Do they aspire to garner users?

I think ML-2000 is quite dead, but there were some promising ideas.

More current is (http://successor-ml.org).  This starts from SML and
plans to add various features.  Evolution rather than revolution, as
far as I can see.

> What about non-recursive type definitions so types can be superceded?
>
>   type t = ..
>   type rec t = ..

I would rather have error messages if I redefine a name at the same
level of declarations, e.g., the top level of a module.  So, a priori,
all names at the same level are mutually recursive.  But you can, of
course, override names in more local scopes.

>>> Also, what about replacing the built-in list data structure with
>>> something else like a rope?
>> 
>> I'm not sure what you mean by "rope" here.
>
> A balanced binary tree:
>
>   http://eigenclass.org/repos/oropes/head/rope.ml
>
> Offers much faster indexing, subsequence, appending and so forth in exchange
> for slightly slower prepend and decapitate. It would be a better general
> purpose sequence container than a singly linked list.

I think this should just be one of many types that share the same
overloaded list notation (lists, vectors, streams, etc.), but I don't
think it should be the default.

	Torben
0
torbenm (37)
11/16/2007 3:39:06 PM
In article <13jqpf6nc6jep72@corp.supernews.com>,
 Jon Harrop <usenet@jdh30.plus.com> wrote:

> 
> Are you advocating that new languages be designed for use without IDEs?

Of course.  What excuse could there be, to design a new language
that depends on an IDE to overcome design flaws that so many
other languages have managed to avoid?

   Donn Cave, donn@u.washington.edu
0
Donn
11/16/2007 5:42:33 PM
Donn Cave wrote:
> Of course.  What excuse could there be, to design a new language
> that depends on an IDE to overcome design flaws that so many
> other languages have managed to avoid?

So you want monochrome teletype when you could have a hardware-accelerated
GUI with visualization, typesetting, type throwback and so on?

I strongly suggest you look at software development in environments like F#
with Visual Studio and Mathematica. They are vastly more productive.

Even OCaml has rudimentary forms of this.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/16/2007 7:27:38 PM
Donn Cave wrote:
> In article <13jrsa7bgvn8bf9@corp.supernews.com>,
>  Jon Harrop <usenet@jdh30.plus.com> wrote:
>> So you want monochrome teletype when you could have a
>> hardware-accelerated GUI with visualization, typesetting, type throwback
>> and so on?
>> 
>> I strongly suggest you look at software development in environments like
>> F# with Visual Studio and Mathematica. They are vastly more productive.
>> 
>> Even OCaml has rudimentary forms of this.
> 
> There seems to be some confusion here.  I am by no means saying
> that IDEs are useless.  The more IDEs, the better.  They just
> aren't an excuse for a serious syntax flaw.
> 
> If it were a thorny problem, maybe, but since dozens of well
> known languages manage to support an unambiguous block structure,
> it can't be that hard.  If it's a mistake that was made and
> there's nothing to be done about it now, as appears to be the
> case with Objective CAML, maybe, but when I got on I believe
> the subject was new syntax.

Ok, so we're all happy with a new syntax like:

  match x with
  | A -> ...
  | B -> ...
  end

where the "end" is optional.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/16/2007 8:28:02 PM
In article <13jrsa7bgvn8bf9@corp.supernews.com>,
 Jon Harrop <usenet@jdh30.plus.com> wrote:

> Donn Cave wrote:
> > Of course.  What excuse could there be, to design a new language
> > that depends on an IDE to overcome design flaws that so many
> > other languages have managed to avoid?
> 
> So you want monochrome teletype when you could have a hardware-accelerated
> GUI with visualization, typesetting, type throwback and so on?
> 
> I strongly suggest you look at software development in environments like F#
> with Visual Studio and Mathematica. They are vastly more productive.
> 
> Even OCaml has rudimentary forms of this.

There seems to be some confusion here.  I am by no means saying
that IDEs are useless.  The more IDEs, the better.  They just
aren't an excuse for a serious syntax flaw.

If it were a thorny problem, maybe, but since dozens of well
known languages manage to support an unambiguous block structure,
it can't be that hard.  If it's a mistake that was made and
there's nothing to be done about it now, as appears to be the
case with Objective CAML, maybe, but when I got on I believe
the subject was new syntax.

   Donn Cave, donn@u.washington.edu
0
Donn
11/16/2007 8:31:23 PM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> Torben �gidius Mogensen wrote:
>>> There are various "successor ML" projects underway.
>>
>> Do you have any references for them? Do they aspire to garner users?
> 
> I think ML-2000 is quite dead, but there were some promising ideas.

Ok.

> More current is (http://successor-ml.org).  This starts from SML and
> plans to add various features.  Evolution rather than revolution, as
> far as I can see.

Sounds great. Also looks dead though.

The page mentions some ideas that I consider essential for a next-ML:

.. Weakening the value restriction
.. Polymorphic variants
.. Better overloading 
.. OCamldoc style comments
.. Improve grammar so fewer parens are required
.. Unified compilation/build technology
.. Rename real to float

OCaml and F# have shown that these are all great ideas, IMHO.

Misses some others:

.. Labelled and optional arguments.
.. Complex numbers, vectors and matrices
.. Pattern matching over lazy values

and mentions many ideas that I would forget for now:

.. Views
.. Higher-order polymorphism and type constructors
.. First-class polymorphism
.. Existential (data)types
.. GADTs
.. Recursive modules
.. A more expressive signature language
.. Proof obligations 
.. Polymorphic recursion?
.. Higher-order modules? 
....

There is, however, one idea that stands head and shoulders above all others
that I'm kicking myself for never having thought of:

.. sML-IL

What an awesome idea!

>> What about non-recursive type definitions so types can be superceded?
>>
>>   type t = ..
>>   type rec t = ..
> 
> I would rather have error messages if I redefine a name at the same
> level of declarations, e.g., the top level of a module.  So, a priori,
> all names at the same level are mutually recursive.  But you can, of
> course, override names in more local scopes.

Ok.

>>>> Also, what about replacing the built-in list data structure with
>>>> something else like a rope?
>>> 
>>> I'm not sure what you mean by "rope" here.
>>
>> A balanced binary tree:
>>
>>   http://eigenclass.org/repos/oropes/head/rope.ml
>>
>> Offers much faster indexing, subsequence, appending and so forth in
>> exchange for slightly slower prepend and decapitate. It would be a better
>> general purpose sequence container than a singly linked list.
> 
> I think this should just be one of many types that share the same
> overloaded list notation (lists, vectors, streams, etc.), but I don't
> think it should be the default.

Provided I can still pattern match over it as a sequence, I'm happy.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/16/2007 8:53:34 PM
In article <13jrvrf86dcem09@corp.supernews.com>,
 Jon Harrop <usenet@jdh30.plus.com> wrote:

> Ok, so we're all happy with a new syntax like:
> 
>   match x with
>   | A -> ...
>   | B -> ...
>   end
> 
> where the "end" is optional.

My issue wasn't with the syntax for "match", but the syntax
for statement blocks, represented by "..." above, and it's
specifically about block structure implied by separator (;).
If a block structure with multiple statements can happen only
when surrounded by explicit begin/end notations of whatever
sort, then that issue is resolved.

Given that, I can't think of an obvious reason why you would
want an optional "end" notation for "match", since its structure
seems reasonably well defined without it.

   Donn Cave, donn@u.washington.edu
0
Donn
11/16/2007 9:28:36 PM
Donn Cave wrote:

> In article <13jrvrf86dcem09@corp.supernews.com>,
>  Jon Harrop <usenet@jdh30.plus.com> wrote:
>
>> Ok, so we're all happy with a new syntax like:
>> 
>>   match x with
>>   | A -> ...
>>   | B -> ...
>>   end
>> 
>> where the "end" is optional.
>
> My issue wasn't with the syntax for "match", but the syntax
> for statement blocks, represented by "..." above, and it's
> specifically about block structure implied by separator (;).

Well, me thinks, that is where the misunderstanding lies: ';' is not a
statement separator, but rather "connects" statements. Perhaps another
character would have been a more fortunate choice, especially given
the number of C, Pascal and Java programmers in the wild. But the idea
that the syntax is strange mostly goes away if one realizes that ";"
doesn't separate, but connects.

And by the way, there is not "block structure in OCaml IMHO: There are
only funtions and composite function (composed with ";"). If one isn't
sure where a block ends or starts, just use parentheses.

like:   | B -> ( a; b; c )

Regards -- Markus

0
11/17/2007 12:45:41 AM
Donn Cave wrote:
> In article <13jrvrf86dcem09@corp.supernews.com>,
>  Jon Harrop <usenet@jdh30.plus.com> wrote:
>> Ok, so we're all happy with a new syntax like:
>> 
>>   match x with
>>   | A -> ...
>>   | B -> ...
>>   end
>> 
>> where the "end" is optional.
> 
> My issue wasn't with the syntax for "match", but the syntax
> for statement blocks, represented by "..." above, and it's
> specifically about block structure implied by separator (;).
> If a block structure with multiple statements can happen only
> when surrounded by explicit begin/end notations of whatever
> sort, then that issue is resolved.

I'm not sure there is much difference between C and OCaml there. Look
at "if" statements, for example:

  if (i == 0)
    j++;
  else
    j--;
  return j;

  if (i == 0) {
    ++i;
    ++j;
  }

in OCaml, those are:

  if i = 0 then
    incr j
  else
    decr j;
  j

  if i = 0 then begin
    incr i;
    incr j;
  end

I think OCaml gets this right but if you have any examples of ugly statement
blocks in OCaml I'd like to see them.

> Given that, I can't think of an obvious reason why you would
> want an optional "end" notation for "match", since its structure
> seems reasonably well defined without it.

Problems happen when you nest them. In OCaml, you wrap nested "match"
expressions in brackets or between "begin .. end" but it would be more
elegant to simply add an optional "end" after each "match". So the OCaml:

  match x with
  | h::t ->
      begin
        match Lazy.force h with
        | None -> 0
        | Some x -> x
      end
  | [] -> 0

would become:

  match x with
  | h::t ->
      match Lazy.force h with
      | None -> 0
      | Some x -> x
      end
  | [] -> 0

Also worth comparing to F#, which is whitespace sensitive:

  match x with
  | h::t ->
      match Lazy.force h with
      | None -> 0
      | Some x -> x
  | [] -> 0

And if you could pattern match over lazy values you wouldn't need any nested
matches in this case:

  match x with
  | lazy None::t -> 0
  | lazy(Some x)::t -> x
  | [] -> 0

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/17/2007 1:09:59 AM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Misses some others:
>
> . Labelled and optional arguments.

SML does not need labeled arguments because you can use its records
instead.  You get optional arguments by adding functional record
update.  (This even lets you choose among different sets of defaults
for the arguments that you omit -- on a per-call basis -- which goes
beyond what OCaml has to offer.)

The proposal for adding functional record update /is/ on the
successor-ml page.  IIRC, Andreas Rossberg added an experimental
implementation of it to HaMLeT.

  http://successor-ml.org/index.php?title=Functional_record_extension_and_row_capture

The implementation in MLPolyR also adds SML#-style record polymorphism
to the mix.  To see how records plus record extension (even without
record polymorphism) can be used to get optional arguments, see the
"html.mlpr" example on:

  http://ttic.uchicago.edu/~wchae/mlrfw/

Matthias
0
find19 (1244)
11/17/2007 2:14:38 PM
Matthias Blume wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> Misses some others:
>>
>> . Labelled and optional arguments.
> 
> SML does not need labeled arguments because you can use its records
> instead.  You get optional arguments by adding functional record
> update.

Consider this curried OCaml function with labelled arguments:

# let f ~x ~y = x, y;;
val f : x:'a -> y:'b -> 'a * 'b = <fun>

You can apply the arguments without having to specify the labels:

# f 2 3;;
- : int * int = (2, 3)

You can partially apply the curried arguments out of order:

# let g = f ~y:3;;
val g : x:'a -> 'a * int = <fun>
# g 2;;
- : int * int = (2, 3)

How does that translate into sML?

> The proposal for adding functional record update /is/ on the
> successor-ml page.  IIRC, Andreas Rossberg added an experimental
> implementation of it to HaMLeT.

If I might just ask for clarification here: is the idea to have structurally
typed records and this functional record update extension to SML lets you
take an existing value of an existing (possibly implicit?) record type and
add new fields to it? So this is more closely related to OCaml's objects
except that you cannot pattern match over those?

> The implementation in MLPolyR also adds SML#-style record polymorphism
> to the mix.  To see how records plus record extension (even without
> record polymorphism) can be used to get optional arguments, see the
> "html.mlpr" example on:
> 
>   http://ttic.uchicago.edu/~wchae/mlrfw/

Here is the sML from that page:

let fun print x = String.output x
    fun printHtml config output =
        (print "<font color="; print (config.color);
         print " size="; print (config.size);
         print " face="; print (config.face);
         print ">"; print output;
         print "</font>";
         print "<br>")

    val default1 = {color="blue", size="3", face="ariel"}
    val default2 = {color="red", size="3", face="ariel"}
in
    (printHtml default1 "Hello, World";
    printHtml (default2 where {size="5"}) "Hello, World";
    printHtml (default1 where {size="10", color="green"}) "Hello, World";
    0)
end

Here is an OCaml equivalent:

  let print_html1 ?(color="blue") ?(size=3) ?(face="ariel") output =
    printf "<font color=%s size=%d face=%s>%s</font><br>"
      color size face output;;

  let print_html2 ?(color="red") = print_html1 ~color;;

  print_html1 "Hello, World";;
  print_html2 ~size:5 "Hello, World";;
  print_html1 ~size:10 ~color:"green" "Hello, World";;

> (This even lets you choose among different sets of defaults
> for the arguments that you omit -- on a per-call basis -- which goes
> beyond what OCaml has to offer.)

In the above example, the print_html1 and print_html2 functions exploit
curried optional arguments to allow you to choose among different sets of
defaults for the arguments that you omit on a per-call basis.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/17/2007 3:02:32 PM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Matthias Blume wrote:
>> Jon Harrop <usenet@jdh30.plus.com> writes:
>>> Misses some others:
>>>
>>> . Labelled and optional arguments.
>> 
>> SML does not need labeled arguments because you can use its records
>> instead.  You get optional arguments by adding functional record
>> update.
>
> Consider this curried OCaml function with labelled arguments:
>
> # let f ~x ~y = x, y;;
> val f : x:'a -> y:'b -> 'a * 'b = <fun>
>
> You can apply the arguments without having to specify the labels:
>
> # f 2 3;;
> - : int * int = (2, 3)
>
> You can partially apply the curried arguments out of order:
>
> # let g = f ~y:3;;
> val g : x:'a -> 'a * int = <fun>
> # g 2;;
> - : int * int = (2, 3)
>
> How does that translate into sML?

It doesn't, and I don't consider that a bad thing.  If a function
takes labeled arguments, then the labels need to be specified at the
call site.  And while I don't like curried arguments very much in the
first place, I'm sure it would be possible to add some syntactic sugar
for a "partial" application.

Anyway, your original request was about labeled and optional
arguments, not about curried arguments.

> If I might just ask for clarification here: is the idea to have structurally
> typed records and this functional record update extension to SML lets you
> take an existing value of an existing (possibly implicit?) record type and
> add new fields to it? So this is more closely related to OCaml's objects
> except that you cannot pattern match over those?

Yes.  Also, there is no subtyping.

>> The implementation in MLPolyR also adds SML#-style record polymorphism
>> to the mix.  To see how records plus record extension (even without
>> record polymorphism) can be used to get optional arguments, see the
>> "html.mlpr" example on:
>> 
>>   http://ttic.uchicago.edu/~wchae/mlrfw/
>
> Here is the sML from that page:
>

[code snipped]

>
> Here is an OCaml equivalent:
>
[code snipped]
>
> In the above example, the print_html1 and print_html2 functions exploit
> curried optional arguments to allow you to choose among different sets of
> defaults for the arguments that you omit on a per-call basis.

Of course, I was not saying that you cannot achieve the same effect
somehow in OCaml.  My point is that one does not need an additional
language feature.  Records and record polymorphism are completely
orthogonal to lambda and application.  Labeled arguments in OCaml are
not.

The fact that you can exploit curried arguments is a coincidence
(because the two defaults are the same except for one field).  The
same coincidence could have been exploited in the MLPolyR code by
declaring the second default in terms of the first using functional
record update.

Matthias
0
find19 (1244)
11/18/2007 5:22:21 AM
Matthias Blume wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> Consider this curried OCaml function with labelled arguments:
>>
>> # let f ~x ~y = x, y;;
>> val f : x:'a -> y:'b -> 'a * 'b = <fun>
>>
>> You can apply the arguments without having to specify the labels:
>>
>> # f 2 3;;
>> - : int * int = (2, 3)
>>
>> You can partially apply the curried arguments out of order:
>>
>> # let g = f ~y:3;;
>> val g : x:'a -> 'a * int = <fun>
>> # g 2;;
>> - : int * int = (2, 3)
>>
>> How does that translate into sML?
> 
> It doesn't, and I don't consider that a bad thing.

Ok. So OCaml has already implemented this and shown that those two bits of
functionality are useful in practice. So I think OCaml is a good benchmark
for comparing similar ideas for sML in this context.

> If a function 
> takes labeled arguments, then the labels need to be specified at the
> call site. And while I don't like curried arguments very much in the 
> first place, I'm sure it would be possible to add some syntactic sugar
> for a "partial" application.

I will be happy provided sML can compete in terms of expressiveness and
brevity.

> Anyway, your original request was about labeled and optional
> arguments, not about curried arguments.

Consider this an amendment then. :-)

Perhaps it would be useful to enumerate the features offered by existing
alternatives like OCaml before trying to draw comparisons. There are
various other benefits that I haven't cited and some problems as well.

>> If I might just ask for clarification here: is the idea to have
>> structurally typed records and this functional record update extension to
>> SML lets you take an existing value of an existing (possibly implicit?)
>> record type and add new fields to it? So this is more closely related to
>> OCaml's objects except that you cannot pattern match over those?
> 
> Yes.  Also, there is no subtyping.

You mean you can't use an sML record in a place requiring a subset of its
fields? If so, I don't think that will affect the utility of this approach.

>> In the above example, the print_html1 and print_html2 functions exploit
>> curried optional arguments to allow you to choose among different sets of
>> defaults for the arguments that you omit on a per-call basis.
> 
> Of course, I was not saying that you cannot achieve the same effect
> somehow in OCaml.  My point is that one does not need an additional
> language feature.  Records and record polymorphism are completely
> orthogonal to lambda and application.  Labeled arguments in OCaml are
> not.

I appreciate that you would like to add only orthogonal features to the SML
language. However, the benefits of OCaml's existing approach seem to stem
from combining these features in such a way that the sum is more than the
parts. So I think you will have to mix the different aspects in the end,
even if you refer to the mixing as syntactic sugar. Perhaps that is
preferable from a design perspective (I have no idea) but I would like to
see a competitive result.

Look what happens in sML when the function with optional arguments is in a
distant module (this is very likely):

  MyModule.func MyModule.default arg

compared to OCaml's existing approach:

  MyModule.func arg

This difference is a direct result of having to store the function
separately from its default arguments in sML.

A similar bloating problem arises if you do not have something similar to
polymorphic variants. Look at this definition of a function to define the
stroke type of an axis in our commercial vector graphics software, for
example:

  let frame =
    Style.Stroke.make ~endcaps:(`None,`None) ~joins:`Mitre ~dashing:[]

  let axes = frame 3.
  let tick = frame 1.

Even if you add the necessary record extensions to SML you are still looking
at:

  val frame_default =
    {Style.Stroke.default with
     endcaps = (Style.Stroke.EndCap.None, Style.Stroke.EndCap.None);
     joins = Style.Stroke.Join.Mitre;
     dashing = []}

  val axes = Style.Stroke.make frame_default 3.0
  val tick = Style.Stroke.make frame_default 1.0

Note that sML would not be "bad" on the scale of things if it didn't
implement these features: it would simply be in a class with Java and C#
rather than OCaml. I think that would be a shame because OCaml has already
implemented and tested these approaches and shown them to be very useful.

As an aside, these are among the top-priority features that I would like
added to F#. In particular, these features must be added before people
start building significant libraries written in F#.

> The fact that you can exploit curried arguments is a coincidence
> (because the two defaults are the same except for one field).  The
> same coincidence could have been exploited in the MLPolyR code by
> declaring the second default in terms of the first using functional
> record update.

There is no difference between the two approaches in that respect, yes.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/18/2007 1:48:06 PM
Jon Harrop <usenet@jdh30.plus.com> writes:

>> It doesn't, and I don't consider that a bad thing.
>
> Ok. So OCaml has already implemented this and shown that those two bits of
> functionality are useful in practice. So I think OCaml is a good benchmark
> for comparing similar ideas for sML in this context.

I find it ugly, so I disagree.

> Perhaps it would be useful to enumerate the features offered by existing
> alternatives like OCaml before trying to draw comparisons.

No, this is not useful.  "Designing languages by piling features upon
features..."

>> Yes.  Also, there is no subtyping.
>
> You mean you can't use an sML record in a place requiring a subset of its
> fields? If so, I don't think that will affect the utility of this
> approach.

I place that expects a subset can be polymorphic in the "rest" of the
record, so in many cases you can get a form of subtyping via row
polymorphism.

> Look what happens in sML when the function with optional arguments is in a
> distant module (this is very likely):
>
>   MyModule.func MyModule.default arg
>
> compared to OCaml's existing approach:
>
>   MyModule.func arg
>
> This difference is a direct result of having to store the function
> separately from its default arguments in sML.

I actually like the former better that the latter, since it makes things
explicit so that I can understand them when I look at my code later
(or at someone else's code).

> [...] I think that would be a shame because OCaml has already
> implemented and tested these approaches and shown them to be very useful.

The last part is the personal subjective judgment that I don't believe.

Matthias
0
find19 (1244)
11/18/2007 5:02:41 PM
Matthias Blume wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>>> It doesn't, and I don't consider that a bad thing.
>>
>> Ok. So OCaml has already implemented this and shown that those two bits
>> of functionality are useful in practice. So I think OCaml is a good
>> benchmark for comparing similar ideas for sML in this context.
> 
> I find it ugly, so I disagree.

Ok.

>> Perhaps it would be useful to enumerate the features offered by existing
>> alternatives like OCaml before trying to draw comparisons.
> 
> No, this is not useful.  "Designing languages by piling features upon
> features..."
> 
>>> Yes.  Also, there is no subtyping.
>>
>> You mean you can't use an sML record in a place requiring a subset of its
>> fields? If so, I don't think that will affect the utility of this
>> approach.
> 
> I place that expects a subset can be polymorphic in the "rest" of the
> record, so in many cases you can get a form of subtyping via row
> polymorphism.
> 
>> Look what happens in sML when the function with optional arguments is in
>> a distant module (this is very likely):
>>
>>   MyModule.func MyModule.default arg
>>
>> compared to OCaml's existing approach:
>>
>>   MyModule.func arg
>>
>> This difference is a direct result of having to store the function
>> separately from its default arguments in sML.
> 
> I actually like the former better that the latter, since it makes things
> explicit so that I can understand them when I look at my code later
> (or at someone else's code).
> 
>> [...] I think that would be a shame because OCaml has already
>> implemented and tested these approaches and shown them to be very useful.
> 
> The last part is the personal subjective judgment that I don't believe.

Ok.

If we can't even agree on optional arguments then I think there is no hope
of building a language as useful as OCaml or F# let alone something better.

Perhaps the best angle for my efforts would be to address OCaml's
shortcomings using macros. That can only go so far but perhaps it can close
the gap between open source and Microsoft's innovations.

Another alternative would be to persuade Apple that they should also
innovate in the direction of ML.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/20/2007 11:50:59 AM
Jon Harrop <usenet@jdh30.plus.com> writes:


> Another alternative would be to persuade Apple that they should also
> innovate in the direction of ML.

Why Apple?  If you are thinking that anything with an Apple stamp will
immediately take over the world, forget it.  Look at what happened
(or, rather, didn't happen) with Dylan, which AFAIK has been Apple's
only serious effort in programming languages.

IMO, a better result would come of someone could get Mozilla to move
their browser development to a functional language.  This is one area
where functional languages should excel: Buffer overflow flaws require
an effort rather than lack of effort if you program in a functional
language, and all the symbolic manipulation of HTML, XML, Javascript,
etc. seems like a perfect fit for functional languages.  And if a
future version of Firefox is in a functional language, all the myriad
contributors will have to learn and love this language.

So, basically, what you need is not a closed system using functional
languages or some company promoting application developers to use
functional languages, but some major open source project with
thousands of contributors moving to a functional language as the main
(or only) development language.

	Torben
0
torbenm5 (42)
11/20/2007 4:09:27 PM
In article <13jsgc6cdmu3r1a@corp.supernews.com>,
 Jon Harrop <usenet@jdh30.plus.com> wrote:


> I think OCaml gets this right but if you have any examples of ugly statement
> blocks in OCaml I'd like to see them.

You've already seen it.  I'm not saying it's ugly - I mean,
if we want to get into what I think is ugly in Objective CAML,
then let me know, but I suppose that really isn't interesting.
Since people apparently still mostly use the old style syntax
even after the introduction of the camlp4 improved syntax, I can
only say there's no accounting for taste.  But in this case I'm
talkin about structural ambiguity that can lead the unwary to
make errors.

Haskell has very similar rules, in its non-indented syntax
option, but resolves it with non-optional begin/end braces,
in I believe every possible case.  Your optional match with ... end
might serve the same, as would parentheses around (match with ...),
but to get rid of the ambiguity you have to make one or the other
non-optional.

Personally, I would use Haskell syntax, and since Haskell works
for me at the moment, my interest in this is rather academic.
I'm going to assume I have written enough on this matter by now,
since it's really pretty simple.

   Donn Cave, donn@u.washington.edu
0
Donn
11/20/2007 9:39:32 PM
Torben �gidius Mogensen wrote:
> Why Apple?

Sun might be another possibility given that the JVM is the main competitor
to .NET.

> If you are thinking that anything with an Apple stamp will 
> immediately take over the world, forget it.  Look at what happened
> (or, rather, didn't happen) with Dylan, which AFAIK has been Apple's
> only serious effort in programming languages.

I'm thinking Apple could gain a lot from adopting a functional programming
language and you just have to demonstrate this to them (e.g. compare F#
with Objective C). Also, my goal is to make a useful tool that gets used
rather than to "take over the world".

> IMO, a better result would come of someone could get Mozilla to move
> their browser development to a functional language.  This is one area
> where functional languages should excel: Buffer overflow flaws require
> an effort rather than lack of effort if you program in a functional
> language,

Functional languages often make it easy to stack overflow instead, and
sometimes make it prohibitively difficult to run in a usable amount of
time.

> and all the symbolic manipulation of HTML, XML, Javascript, 
> etc. seems like a perfect fit for functional languages.

How many functional languages even have standards compliant XML
implementations, let alone error correcting HTML parsers?

> And if a 
> future version of Firefox is in a functional language, all the myriad
> contributors will have to learn and love this language.
>
> So, basically, what you need is not a closed system using functional
> languages or some company promoting application developers to use
> functional languages, but some major open source project with
> thousands of contributors moving to a functional language as the main
> (or only) development language.

That is a nice goal but we need a decent functional language and
implementation first.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/21/2007 2:53:51 AM
Jon Harrop <usenet@jdh30.plus.com> writes:

> Torben �gidius Mogensen wrote:
>> Why Apple?
>
> Sun might be another possibility given that the JVM is the main competitor
> to .NET.
>
>> If you are thinking that anything with an Apple stamp will 
>> immediately take over the world, forget it.  Look at what happened
>> (or, rather, didn't happen) with Dylan, which AFAIK has been Apple's
>> only serious effort in programming languages.
>
> I'm thinking Apple could gain a lot from adopting a functional programming
> language and you just have to demonstrate this to them (e.g. compare F#
> with Objective C). Also, my goal is to make a useful tool that gets used
> rather than to "take over the world".

Dylan is a mostly functional language.  It was inspired by LISP.

>> IMO, a better result would come of someone could get Mozilla to move
>> their browser development to a functional language.  This is one area
>> where functional languages should excel: Buffer overflow flaws require
>> an effort rather than lack of effort if you program in a functional
>> language,
>
> Functional languages often make it easy to stack overflow instead,

This depends on the implementation, and is easy to avoid with a decent
implementation.  For example, SML/NJ doesn't use a stack at all --
everything is put in the heap.

> and sometimes make it prohibitively difficult to run in a usable
> amount of time.

I don't agree.  Functional languages can be competitive with C or C++
for many tasks, especially the kind of task you need in a browser.

>> and all the symbolic manipulation of HTML, XML, Javascript, 
>> etc. seems like a perfect fit for functional languages.
>
> How many functional languages even have standards compliant XML
> implementations, let alone error correcting HTML parsers?

None have these built in, but neither do C, C++, Java, C# etc.  We are
not talking about texisting code, we are talking about languages.

>> And if a 
>> future version of Firefox is in a functional language, all the myriad
>> contributors will have to learn and love this language.
>>
>> So, basically, what you need is not a closed system using functional
>> languages or some company promoting application developers to use
>> functional languages, but some major open source project with
>> thousands of contributors moving to a functional language as the main
>> (or only) development language.
>
> That is a nice goal but we need a decent functional language and
> implementation first.

If the goal is to be more decent than C (which is what is currently
used for Firefox), we have long since passed that.  Don't wait for
something better -- start using what we have.  Sure, next year will
bring something better, but that will also be true next year or in ten
years.

And the best way to ensure that we have a "decent functional language
and implementation" is to start working on it.

	Torben
0
11/21/2007 9:07:37 AM
Probably worth mentioning that Sun is currently involved in the
development of the Fortress programming language.  Fortress is being
influenced by functional programming languages - with Guy Steele at
the helm, you would expect it to be.  But it's not really a functional
language per se.

Chris

On Nov 20, 8:53 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
>
> Sun might be another possibility given that the JVM is the main competitor
> to .NET.
>
0
11/21/2007 5:01:31 PM
In article 
<dd66cd2b-c144-4226-a716-0c6cec2fd9e1@d61g2000hsa.googlegroups.com>,
 Chris Rathman <Chris.Rathman@tx.rr.com> wrote:

> Probably worth mentioning that Sun is currently involved in the
> development of the Fortress programming language.  Fortress is being
> influenced by functional programming languages - with Guy Steele at
> the helm, you would expect it to be.

Why should one expect that?

He was also on the Fortran and C standards committees (ANSI),
he co-authored a book on C and one on High Performance
Fortran. Are those influenced by functional programming
languages, too?

>  But it's not really a functional
> language per se.
> 
> Chris
> 
> On Nov 20, 8:53 pm, Jon Harrop <use...@jdh30.plus.com> wrote:
> >
> > Sun might be another possibility given that the JVM is the main competitor
> > to .NET.
> >

-- 
http://lispm.dyndns.org/
0
joswig8642 (2203)
11/21/2007 5:32:10 PM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> I'm thinking Apple could gain a lot from adopting a functional
>> programming language and you just have to demonstrate this to them (e.g.
>> compare F# with Objective C). Also, my goal is to make a useful tool that
>> gets used rather than to "take over the world".
> 
> Dylan is a mostly functional language.  It was inspired by LISP.

True. Should have said ML...

>> Functional languages often make it easy to stack overflow instead,
> 
> This depends on the implementation, and is easy to avoid with a decent
> implementation.  For example, SML/NJ doesn't use a stack at all --
> everything is put in the heap.

As I understand it, CPS and laziness are an impediment to FFI.

>> How many functional languages even have standards compliant XML
>> implementations, let alone error correcting HTML parsers?
> 
> None have these built in, but neither do C, C++, Java, C# etc.  We are
> not talking about texisting code, we are talking about languages.

On the contrary, I could not be less interested in discussing the
theoretical properties of these languages and disregarding what you can do
with them and whether or not they actually work in practice. Of what little
you can even claim to be able to do with modern FPLs, much doesn't work in
practice.

I most recently rediscovered this with Haskell. I said to the community "I'm
interested in using OpenGL from Haskell". They say "wonderful, we have a
wide range of robust and very efficient OpenGL bindings and some have even
been implemented, here's a demo". I try to run the demo (Frag) and it
segfaults. Turns out the performance of this modern FPL was so poor that
the author was forced to resort to assembler style coding just to get it to
work and accidentally made his implementation 32-bit only.

Take your example of writing a web browser in a modern FPL. Forget about
competing with Firefox and just consider what is required to write a
bare-bones browser:

.. Networking libraries: are any HTTPS bindings for any of these languages
even out of alpha quality?

.. Error-correcting HTML parsing: requires a huge effort to try to correct
real pages accurately. Apple failed to do this with Safari, for example.

.. GUI: are any bindings even out of alpha quality, e.g. OCaml's freetype
bindings don't support kerning and the whole camlimages library only has
281 Ubuntu installs?

Mono overtook OCaml in the Debian package popularity contest this year:

http://people.debian.org/~igloo/popcon-graphs/index.php?packages=ocaml%2Cmono&show_installed=on&want_legend=on&from_date=&to_date=&hlght_date=&date_fmt=%25Y-%25m&beenhere=1

I suspect the reason is that interoperability is limiting the uptake of
modern FPLs.

Consider what software that was written in these languages has become
popular and why:

FFTW is a great success with hundreds of thousands of installations on Linux
alone. Why? Because the library can be compiled from intermediate C and run
without needing an OCaml run time: most users don't even know it was
written in OCaml. That's great but it isn't applicable to most software.
Even if you could compile OCaml code to a DLL, it wouldn't be able to
interoperate with other OCaml code (because there is no common run-time)
let alone anything else. This is why I really like the idea of an sMLIL.

>> That is a nice goal but we need a decent functional language and
>> implementation first.
> 
> If the goal is to be more decent than C (which is what is currently
> used for Firefox), we have long since passed that.

Looks like IceWeasel is C++ to me and none of the modern FPLs come close to
the level of interoperability that C++ offers.

> Don't wait for something better -- start using what we have.

I am one of the only people in the world trying to write mainstream
commercial software in ML and I'm telling you that what we have is
inadequate: you cannot compile and distribute software written in OCaml
that will run reliably if you use interop (OpenGL in my case). However,
with relatively little effort a language implementor could make something
more than adequate and an SML equivalent of the JVM is an excellent idea,
not least because it would allow the fragmented community to at least share
an FFI and bindings, requiring only a native shim for each language.

> Sure, next year will bring something better, but that will also be true
> next year or in ten years. 

I've been waiting ten years for useful improvements to SML and still there
is nothing. There isn't even consensus about what I consider to be trivial
and essential improvements.

> And the best way to ensure that we have a "decent functional language
> and implementation" is to start working on it.

Perhaps that is the only way forward for me at this point in time...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/21/2007 6:04:54 PM
I was thinking more of his work on Scheme.  Anyhow, I was trying to
point out that Sun does have an effort underway for another PL - one
which aims at scientific and mathematical computing.  But even if it's
influenced by FP, it's not likely to be an FP language.

Chris

Rainer Joswig wrote:
> In article
> <dd66cd2b-c144-4226-a716-0c6cec2fd9e1@d61g2000hsa.googlegroups.com>,
>  Chris Rathman <Chris.Rathman@tx.rr.com> wrote:
>
> > Probably worth mentioning that Sun is currently involved in the
> > development of the Fortress programming language.  Fortress is being
> > influenced by functional programming languages - with Guy Steele at
> > the helm, you would expect it to be.
>
> Why should one expect that?
>
> He was also on the Fortran and C standards committees (ANSI),
> he co-authored a book on C and one on High Performance
> Fortran. Are those influenced by functional programming
> languages, too?
0
11/21/2007 6:33:23 PM
Chris Rathman wrote:
> I was thinking more of his work on Scheme.  Anyhow, I was trying to
> point out that Sun does have an effort underway for another PL - one
> which aims at scientific and mathematical computing.  But even if it's
> influenced by FP, it's not likely to be an FP language.

We can hope. :-)

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/21/2007 7:49:31 PM
Chris Rathman wrote:
> Probably worth mentioning that Sun is currently involved in the
> development of the Fortress programming language.  Fortress is being
> influenced by functional programming languages - with Guy Steele at
> the helm, you would expect it to be.  But it's not really a functional
> language per se.

Now that I've read a bit more about Fortress I must say I'm not appreciating
the fountains of knowledge that they are drawing upon (Java and Scala).

Makes me want to try ocamljava again... :-)

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/21/2007 8:15:41 PM
Jon Harrop wrote:
>
> On the contrary, I could not be less interested in discussing the
> theoretical properties of these languages and disregarding what 
 > you can do with them and whether or not they actually work in
 > practice. Of what little you can even claim to be able to do with
 > modern FPLs, much doesn't work in practice.

As always when you write "modern FPLs", I get the distinct feeling
that you are excluding Erlang...

There is tons of commercial software built in Erlang, and
most Erlang users are in fact using it commercially. Erlang
is younger than ML, but older than Haskell. Perhaps "modern"
is a euphemism for "based on the H-M type system"?

> I most recently rediscovered this with Haskell. I said to the
 > community "I'm interested in using OpenGL from Haskell". [...]
 > Turns out the performance of this modern FPL was so poor that
> the author was forced to resort to assembler style coding just
 > to get it to work and accidentally made his implementation
 > 32-bit only.

This seems like a very specific gripe. If you'd be looking for
an OpenGL binding for Erlang, the "demo" would be the Wings3D
modelling application (http://www.wings3d.com/). We used to track
many thousand downloads/month of Erlang bundled with Wings3d,
but eliminated the entries, as they were skewing the Erlang
download stats too much.

I have no idea whether the OpenGL binding is prepared for
64-bit, but it is most certainly out of alpha.


> Take your example of writing a web browser in a modern FPL.
 > Forget about competing with Firefox and just consider what is
 > required to write a bare-bones browser:
> 
> . Networking libraries: are any HTTPS bindings for any of
 > these languages even out of alpha quality?

Not that I know of anyone having written a web browser in
Erlang (well... I think Tony Rogvall did once), but Nortel
have sold a number of Erlang-based web server applications
that are best-in-class in terms of SSL scalability. As
far as server-side HTTPS goes, there are several robust
commercial Erlang-based installations out there.


> . Error-correcting HTML parsing: requires a huge effort to
 > try to correct real pages accurately. Apple failed to do
 > this with Safari, for example.

Huge effort, true. If there were any reliable measure of
accuracy, it would most certainly be less difficult. The
main problem is of course that the pages contain erroneous
HTML, and correcting them amounts to a guessing game. Your
software needs to guess essentially as IE does, and also
render the result in the same way. Of course the only way to
verify this is through trial and error (unless you have access
to the IE sources).

The thing about crying for product-quality libraries is that
if your requirements match those of somebody else, who's
taken the time to develop product-quality stuff (and is
willing to share), then you may be in luck. You're likely
to find areas that your FPL distro doesn't cover, much like
there are plenty of problems for which you'd have to search
to find a successful Java-based implementation.

I've had reason to explore C++-based alternatives to Erlang
code for commercial components, and on several occasions,
we've found that it would be better and cheaper to develop
from scratch ourselves than trying to integrate an existing
C++-based component. Over the last decade, we've had this
proven over and over again - sometimes by buying commercial
components, only to determine later that we would have been
better off not to, and sometimes by writing our own code, and
finding it an order of magnitude more compact, more reliable,
easier to debug, and often with better performance than we
could have gotten otherwise. We've had several occasions where
we did buy 3rd party software and were happy with it, but if
I were to generalize, it's only worth buying for very special
components, like BGP routing stacks, error-correcting HTML
parsers, etc.

Your experience with ML sounds depressing, which seems ironic,
considering how much you've bragged about it in various
forums. I'm not sure I get it.

If you want your favourite FPL to compete heads-on with C++,
then you're bound to be disappointed. That shouldn't be taken
as proof that the technology isn't competitive in areas where
it's strong, and condemning a whole family of languages
because you are frustrated within your own niche is an insult
to those who have been able to achieve excellent results
in other areas.


BR,
Ulf W
0
ulf.wiger (50)
11/21/2007 10:55:48 PM
Ulf Wiger wrote:
> Jon Harrop wrote:
>> On the contrary, I could not be less interested in discussing the
>> theoretical properties of these languages and disregarding what
>  > you can do with them and whether or not they actually work in
>  > practice. Of what little you can even claim to be able to do with
>  > modern FPLs, much doesn't work in practice.
> 
> As always when you write "modern FPLs", I get the distinct feeling
> that you are excluding Erlang...

Yes, sorry. Nothing against Erlang but I couldn't think of a better name.

> There is tons of commercial software built in Erlang, and
> most Erlang users are in fact using it commercially. Erlang
> is younger than ML, but older than Haskell. Perhaps "modern"
> is a euphemism for "based on the H-M type system"?

I was basically referring to OCaml and Haskell in this case and Scala and F#
elsewhere.

>> I most recently rediscovered this with Haskell. I said to the
>  > community "I'm interested in using OpenGL from Haskell". [...]
>  > Turns out the performance of this modern FPL was so poor that
>> the author was forced to resort to assembler style coding just
>  > to get it to work and accidentally made his implementation
>  > 32-bit only.
> 
> This seems like a very specific gripe.

It is one example of many.

> If you'd be looking for 
> an OpenGL binding for Erlang, the "demo" would be the Wings3D
> modelling application (http://www.wings3d.com/). We used to track
> many thousand downloads/month of Erlang bundled with Wings3d,
> but eliminated the entries, as they were skewing the Erlang
> download stats too much.

Yes.

>> . Networking libraries: are any HTTPS bindings for any of
>  > these languages even out of alpha quality?
> 
> Not that I know of anyone having written a web browser in
> Erlang (well... I think Tony Rogvall did once), but Nortel
> have sold a number of Erlang-based web server applications
> that are best-in-class in terms of SSL scalability. As
> far as server-side HTTPS goes, there are several robust
> commercial Erlang-based installations out there.

That puts Erlang a long way ahead of the other languages in this respect
then. In OCaml there is virtually nothing for networking, XML, HTML or
databases. There are some dinky little projects, of course, but you can
waste a lot of time trying to find one that will happen to work for you.
Nothing with a significant user base or decent examples.

There are even examples of web browsers written in OCaml, as Torben hinted
at, but these are long since extinct for the reasons I gave.

>> . Error-correcting HTML parsing: requires a huge effort to
>  > try to correct real pages accurately. Apple failed to do
>  > this with Safari, for example.
> 
> Huge effort, true. If there were any reliable measure of
> accuracy, it would most certainly be less difficult. The
> main problem is of course that the pages contain erroneous
> HTML, and correcting them amounts to a guessing game. Your
> software needs to guess essentially as IE does, and also
> render the result in the same way. Of course the only way to
> verify this is through trial and error (unless you have access
> to the IE sources).

Exactly.

> The thing about crying for product-quality libraries is that
> if your requirements match those of somebody else, who's
> taken the time to develop product-quality stuff (and is
> willing to share), then you may be in luck. You're likely
> to find areas that your FPL distro doesn't cover, much like
> there are plenty of problems for which you'd have to search
> to find a successful Java-based implementation.

Sure but decent libraries don't need to be rewritten in these languages: you
only need decent documented interop and users will write the bindings
themselves.

In the future, OCaml's growth will continue to be stifled by poor interop
whereas F# will grow much more easily thanks to excellent interop.

We can fix this by writing a new ML implementation that offers the most
valuable features without the baggage that afflicts OCaml.

> I've had reason to explore C++-based alternatives to Erlang
> code for commercial components, and on several occasions,
> we've found that it would be better and cheaper to develop
> from scratch ourselves than trying to integrate an existing
> C++-based component. Over the last decade, we've had this
> proven over and over again - sometimes by buying commercial
> components, only to determine later that we would have been
> better off not to, and sometimes by writing our own code, and
> finding it an order of magnitude more compact, more reliable,
> easier to debug, and often with better performance than we
> could have gotten otherwise. We've had several occasions where
> we did buy 3rd party software and were happy with it, but if
> I were to generalize, it's only worth buying for very special
> components, like BGP routing stacks, error-correcting HTML
> parsers, etc.

Right.

> Your experience with ML sounds depressing, which seems ironic,
> considering how much you've bragged about it in various
> forums. I'm not sure I get it.

My experience is far from depressing. I have found these languages to be
enormously productive for a wide range of tasks. So much so that Microsoft
picked up the ball and are now running with it.

I simply want to see free software on Linux that can compete with what F# is
becoming. The F# team looked at the existing languages, stole the most
valuable features, fixed the most intrusive problems, shipped an awesome
tool and now they are really knuckling down to polish it.

> If you want your favourite FPL to compete heads-on with C++,
> then you're bound to be disappointed.  That shouldn't be taken 
> as proof that the technology isn't competitive in areas where
> it's strong, and condemning a whole family of languages
> because you are frustrated within your own niche is an insult
> to those who have been able to achieve excellent results
> in other areas.

I'm certainly not condemning a whole family of languages. I'm simply looking
at them objectively and pointing out deficiencies that are currently
stifling their growth in the hope that they can be fixed.

A new language and implementation that draws upon the success of Haskell,
OCaml and F# could address this. Hopefully one will emerge but I've no idea
where from.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/22/2007 2:54:00 AM
Jon Harrop <usenet@jdh30.plus.com> writes:


> As I understand it, CPS and laziness are an impediment to FFI.

If you can define strict unboxed types like in Haskell, FFI is no
problem even if the default evaluation is lazy.  Similarly, you can
get around CPS fairly easy by treating foreign calls like basic
operators.

>>> How many functional languages even have standards compliant XML
>>> implementations, let alone error correcting HTML parsers?
>> 
>> None have these built in, but neither do C, C++, Java, C# etc.  We are
>> not talking about texisting code, we are talking about languages.
>
> On the contrary, I could not be less interested in discussing the
> theoretical properties of these languages and disregarding what you can do
> with them and whether or not they actually work in practice. Of what little
> you can even claim to be able to do with modern FPLs, much doesn't work in
> practice.

You are comparing projects with many man years of work in C etc. with
one-person hobby projects in functional languages, so it is no wonder
that the functional languages get the short stick.  If you, instead,
compared mature projects written in functional languages with hobby
projects written in C, you would get a different result.

	Torben
0
torbenm (37)
11/22/2007 10:14:21 AM
Torben �gidius Mogensen wrote:
> Jon Harrop <usenet@jdh30.plus.com> writes:
>> As I understand it, CPS and laziness are an impediment to FFI.
> 
> If you can define strict unboxed types like in Haskell, FFI is no
> problem even if the default evaluation is lazy.  Similarly, you can
> get around CPS fairly easy by treating foreign calls like basic
> operators.

Ok.

>>>> How many functional languages even have standards compliant XML
>>>> implementations, let alone error correcting HTML parsers?
>>> 
>>> None have these built in, but neither do C, C++, Java, C# etc.  We are
>>> not talking about texisting code, we are talking about languages.
>>
>> On the contrary, I could not be less interested in discussing the
>> theoretical properties of these languages and disregarding what you can
>> do with them and whether or not they actually work in practice. Of what
>> little you can even claim to be able to do with modern FPLs, much doesn't
>> work in practice.
> 
> You are comparing projects with many man years of work in C etc. with
> one-person hobby projects in functional languages, so it is no wonder
> that the functional languages get the short stick.  If you, instead,
> compared mature projects written in functional languages with hobby
> projects written in C, you would get a different result.

We can compare my work in OCaml with my work in F#, for example. F# makes
certain things much easier and that is a tremendous advantage that Haskell
and OCaml both miss out on.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/22/2007 12:33:18 PM
Jon Harrop skrev:
 > Ulf Wiger wrote:
 >> Your experience with ML sounds depressing, which seems ironic,
 >> considering how much you've bragged about it in various
 >> forums. I'm not sure I get it.
 >
 > My experience is far from depressing. I have found these languages to be
 > enormously productive for a wide range of tasks. So much so that 
Microsoft
 > picked up the ball and are now running with it.
 >
 > I simply want to see free software on Linux that can compete with 
what F# is
 > becoming. The F# team looked at the existing languages, stole the most
 > valuable features, fixed the most intrusive problems, shipped an awesome
 > tool and now they are really knuckling down to polish it.

Ok, understood.


 > I'm certainly not condemning a whole family of languages. I'm simply 
looking
 > at them objectively and pointing out deficiencies that are currently
 > stifling their growth in the hope that they can be fixed.
 >
 > A new language and implementation that draws upon the success of Haskell,
 > OCaml and F# could address this. Hopefully one will emerge but I've 
no idea
 > where from.

Indeed. It may happen in ways we don't foresee, much like C# is picking
up idioms from the FP world, and various languages experiment with
"erlang-style concurrency". We'll just have to wait and see what comes
out of it in the coming years.

BR,
Ulf W
0
ulf.wiger (50)
11/22/2007 3:35:50 PM
Torben �gidius Mogensen wrote:
> You are comparing projects with many man years of work in C etc. with
> one-person hobby projects in functional languages, so it is no wonder
> that the functional languages get the short stick.  If you, instead,
> compared mature projects written in functional languages with hobby
> projects written in C, you would get a different result.

Note that for many years Perl was a hobby project of Larry Wall. The
original Unix was a hobby project of two guys.  Array language K was
primarily designed and written by one guy and K programs can analyze
gigabytes of data fast enough to keep multiple disks busy.  Most early C
compilers were one or two people projects and were no slouches.  Bottom
line: write code people want and they will give you plenty of motivation
to improve your code and bragging rights about your language (or code).
0
usenet3730 (115)
11/22/2007 6:15:34 PM
Ulf Wiger wrote:
> Indeed. It may happen in ways we don't foresee, much like C# is picking
> up idioms from the FP world, and various languages experiment with
> "erlang-style concurrency". We'll just have to wait and see what comes
> out of it in the coming years.

C# is doing good things for many ordinary software developers in industry
but F# is definitely the gold standard when it comes to many things that ML
can be good at.

I am interested in the asynchronous workflows in F# and how they draw upon
Erlang but they are of little benefit to me: data parallel libraries are
much more useful here and I have no complicated demands for concurrent
programming.

However, concurrent and parallel programming are a tiny part of how F#
improves upon Haskell and OCaml. A lot of it is down to combining useful
features (i.e. most of OCaml) with easy interoperability but also the fact
that you can commercialize work done in F# as Windows applications and
DLLs.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
11/22/2007 7:33:06 PM
Lauri Alanko <la@iki.fi> wrote:
> In article <fh7l9m$pku$2@oravannahka.helsinki.fi>,
> Vesa Karvonen  <vesa.karvonen@cs.helsinki.fi> wrote:
> > I would call it risky even in a lazy language.  Having cyclic values
> > still breaks quite a few properties.  For example, how do you pickle a
> > cyclic list?  How do you avoid going into an infinite loop while
> > comparing two cyclic lists?

> By adding a reasonably well-behaved extension to support object
> identities:

> http://www.cs.chalmers.se/~koen/pubs/entry-asian99-lava.html

> (Trivial to implement with IORefs and unsafePerformIO.)

> Yes, this breaks referential transparency a bit, but it only brings
> into the semantics some distinctions that already matter
> performance-wise.

Yeah.  This is just the kind of thing that keeps me away from Haskell.
I just find it revolting to have to use utterly unsafe features like
unsafePerformIO or (type unsafe) casts to solve practical problems.
It is amazing how some Haskellers keep pretending such features don't
even exist.  Yet, I've read quite a few Haskell papers that use those
for practically important problems, because safer solutions aren't
satisfactory.

Some time ago, while playing with some toy benchmarks, I noticed that
one Haskell benchmark failed with a stack overflow if it wasn't
compiled with a particular set of compiler options.  Recently I
noticed one Haskell toy benchmark using FFI pointer arithmetic and
poke/peek (presumably) for performance.  Things like that just make me
puke.

-Vesa Karvonen
0
12/11/2007 2:04:19 PM
Vesa Karvonen wrote:
> Lauri Alanko <la@iki.fi> wrote:
>> In article <fh7l9m$pku$2@oravannahka.helsinki.fi>,
>> Vesa Karvonen  <vesa.karvonen@cs.helsinki.fi> wrote:
>> > I would call it risky even in a lazy language.  Having cyclic values
>> > still breaks quite a few properties.  For example, how do you pickle a
>> > cyclic list?  How do you avoid going into an infinite loop while
>> > comparing two cyclic lists?
> 
>> By adding a reasonably well-behaved extension to support object
>> identities:
> 
>> http://www.cs.chalmers.se/~koen/pubs/entry-asian99-lava.html
> 
>> (Trivial to implement with IORefs and unsafePerformIO.)
> 
>> Yes, this breaks referential transparency a bit, but it only brings
>> into the semantics some distinctions that already matter
>> performance-wise.
> 
> Yeah.  This is just the kind of thing that keeps me away from Haskell.
> I just find it revolting to have to use utterly unsafe features like
> unsafePerformIO or (type unsafe) casts to solve practical problems.

Each time you use an FFI bound C library you are using an unsafe feature.
The C code may have bugs that might completely trash your RTS.

> It is amazing how some Haskellers keep pretending such features don't
> even exist.  Yet, I've read quite a few Haskell papers that use those
> for practically important problems, because safer solutions aren't
> satisfactory.

It is important to distinguish between uses of unsafePerformIO that are
semantically visible from the outside and those which are hidden in a
library with a referentially transparent API. The latter is ok, IMO.

> Some time ago, while playing with some toy benchmarks, I noticed that
> one Haskell benchmark failed with a stack overflow if it wasn't
> compiled with a particular set of compiler options.  Recently I
> noticed one Haskell toy benchmark using FFI pointer arithmetic and
> poke/peek (presumably) for performance.  Things like that just make me
> puke.

I agree with you on this one.

Cheers
Ben
0
12/17/2007 1:40:34 AM
Ben Franksen wrote:
> Vesa Karvonen wrote:
>> Yeah.  This is just the kind of thing that keeps me away from Haskell.
>> I just find it revolting to have to use utterly unsafe features like
>> unsafePerformIO or (type unsafe) casts to solve practical problems.
> 
> Each time you use an FFI bound C library you are using an unsafe feature.

Efficient IO should not be an "unsafe" feature though.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/18/2007 4:15:25 PM
On Tue, 18 Dec 2007 16:15:25 +0000, Jon Harrop <usenet@jdh30.plus.com>
wrote:

>Efficient IO should not be an "unsafe" feature though.

IO--of any kind--is inherently unsafe. What if the disk is full? The
source/destination URL is unreachable? Etc.

Steve Schafer
Fenestra Technologies Corp.
http://www.fenestra.com/
0
steve2740 (70)
12/18/2007 4:32:31 PM
Steve Schafer wrote:
> On Tue, 18 Dec 2007 16:15:25 +0000, Jon Harrop <usenet@jdh30.plus.com>
> wrote:
> > Efficient IO should not be an "unsafe" feature though.
> 
> IO--of any kind--is inherently unsafe. What if the disk is full? The
> source/destination URL is unreachable? Etc.

Warning: homonym. The word "safe" had a relatively well-defined meaning here
but you're using a different meaning of the same word. I believe we were
all referring to "safe" languages, i.e. ones that can't cause memory access
violations and so forth.

You can always run out of finite resources like RAM or disk, so that is
usually glossed over. An important point is whether or not a language and
its implementation can prevent programmers from being able to screw up in
certain ways, like buffer over-runs.

Vesa was saying that IO in Haskell can be very slow unless you use unsafe
language features. Like MLs, Haskell strives to be a "safe" language but
what is the value of that if you're forced to resort to unsafe methods for
practically essential features like IO? OCaml has similar problems with its
marshalling: it is "unsafe".

My personal gripe is the lack of support for things like OpenGL in modern
FPLs. I think all modern languages should provide "safe" bindings to GUI
and graphics libraries, like GTK+ and OpenGL. Yet the support for such
things is very poor. Much worse than Python, for example.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/18/2007 5:13:51 PM
On Tue, 18 Dec 2007 16:15:25 +0000, Jon Harrop <usenet@jdh30.plus.com>
wrote:

>Ben Franksen wrote:
>> Vesa Karvonen wrote:
>>> Yeah.  This is just the kind of thing that keeps me away from Haskell.
>>> I just find it revolting to have to use utterly unsafe features like
>>> unsafePerformIO or (type unsafe) casts to solve practical problems.
>> 
>> Each time you use an FFI bound C library you are using an unsafe feature.
>
>Efficient IO should not be an "unsafe" feature though.

But it is.  You'll find that out when you try to implement your own IO
for your compiler (using nifty features of the implementation language
is cheating, you have to write your own IO routines from scratch 8-)

Unfortunately, safety is not an orthogonal dimension.  Efficient IO is
hard and generally quite messy to implement - a nice layered structure
that is easy to understand can add considerable overhead if you are
not careful, particularly for input.  Implementing streams in your
language also adds overhead vs using a simple IO buffer API.  Type
safety will add additional overhead unless it can always be guaranteed
statically at compile time (which may not be possible).

The best you can do is try to balance safety against performance and
hide as much of the messiness as possible behind your API. 

George
--
for email reply remove "/" from address
0
George
12/18/2007 6:06:46 PM
Jon:
> Vesa was saying that IO in Haskell can be very slow unless you use unsafe
> language features.

No, that is not what I was saying.

-Vesa Karvonen
0
12/18/2007 8:42:32 PM
Vesa Karvonen wrote:
> Jon:
>> Vesa was saying that IO in Haskell can be very slow unless you use unsafe
>> language features.
> 
> No, that is not what I was saying.

Indeed.

Jon, could you please stop posting this sort of FUD?

Cheers
Ben
0
12/18/2007 10:10:55 PM
Ben Franksen wrote:
> Vesa Karvonen wrote:
>> Jon:
>>> Vesa was saying that IO in Haskell can be very slow unless you use
>>> unsafe language features.
>> 
>> No, that is not what I was saying.

My mistake.

> Jon, could you please stop posting this sort of FUD?

You can see it in Frag:

  http://www.haskell.org/haskellwiki/Frag

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/18/2007 10:21:05 PM
Jon Harrop wrote:

> Ben Franksen wrote:
>> Vesa Karvonen wrote:
>>> Jon:
>>>> Vesa was saying that IO in Haskell can be very slow unless you use
>>>> unsafe language features.
>>> 
>>> No, that is not what I was saying.
> 
> My mistake.
> 
>> Jon, could you please stop posting this sort of FUD?
> 
> You can see it in Frag:
> 
>   http://www.haskell.org/haskellwiki/Frag

What do you mean? I am completely stupefied that something like this is even
possible in Haskell, with all the real-time stuff needed.

I supose you have looked at the sources and seen lots of comments like

  -- grr, yet another unsafePerformIO needed here, otherwise I/O too slow

Yes?

Cheers
Ben
0
12/19/2007 1:19:17 AM
Ben Franksen wrote:
> What do you mean? I am completely stupefied that something like this is
> even possible in Haskell, with all the real-time stuff needed.

The real time requirements for a game like that are actually comparatively
easy because the game is not CPU intensive.

> I supose you have looked at the sources and seen lots of comments like
> 
>   -- grr, yet another unsafePerformIO needed here, otherwise I/O too slow
> 
> Yes?

Frag loads data from binary formats and, to do so, it uses a lot of unsafe
IO calls (I assume this was done for performance: I can't think of any
other reason to do it). However, these calls somehow assume 32-bit ints
and, consequently, break Frag on 64-bit machines like mine. So I can only
run Frag in a 32-bit chroot.

The point is that the safety of these languages is very confined in
practice, in many ways because they have such poor FFIs. F# has a much
better FFI than OCaml and also provides a lot more "safe" libraries
via .NET. However, the APIs of most .NET libraries are awful compared to
anything you'll find for a "real" FPL. The JVM is even worse than .NET.

I'm not sure what the best solution to this would be but it certainly seems
stupid for each of these tiny communities to try to reinvent OpenGL
bindings, for example. Try to find OpenGL demos written in FPLs that use
vertex and fragment shaders, for example. I just tried writing one in
OCaml. In C++ it is very easy (just a few calls and you've installed your
own Phong shader) but in OCaml you must use experimental GLCaml bindings
rather than the usual LablGL (which is now a decade out of date) but nobody
has ever used shaders from GLCaml so there are no working examples and it
doesn't appear to work. The author (Elliott Oti) is extremely helpful but
someone else will be doing something virtually identical in the Haskell
world, and then the MLton world and then...

IMHO, modern FPL implementations should do as much as possible to reuse each
others bindings. This would make them much more "safe" in practice.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/19/2007 10:12:22 AM
Jon Harrop wrote:
> Ben Franksen wrote:
>> What do you mean? I am completely stupefied that something like this is
>> even possible in Haskell, with all the real-time stuff needed.
> 
> The real time requirements for a game like that are actually comparatively
> easy because the game is not CPU intensive.

But it still needs to take care that whatever it does (graphical I/O,
mostly?) completes fast enough.

>> I supose you have looked at the sources and seen lots of comments like
>> 
>>   -- grr, yet another unsafePerformIO needed here, otherwise I/O too slow
>> 
>> Yes?
> 
> Frag loads data from binary formats and, to do so, it uses a lot of unsafe
> IO calls (I assume this was done for performance: I can't think of any
> other reason to do it). 
> 
> However, these calls somehow assume 32-bit ints
> and, consequently, break Frag on 64-bit machines like mine. So I can only
> run Frag in a 32-bit chroot.

These things have /nothing/ to do with each other.

The word 'unsafe' like in

  foreign import unsafe xxyy...

means that the foreign routine is not supposed to call back into the Haskell
world. Thus, whether a foreign import can safely be made 'unsafe' depends
only on the semantics of the C routine. Naming this 'unsafe' is generally
believed to be misleading. It is planned to rename it in the next standard
to something that indicates better what it means. Using the 'unsafe'
qualifier in a foreign import declaration is indeed done for efficiency
reasons: an 'unsafe' call is a lot cheaper than a 'safe' one.

The 32/64 bit distinction is completely orthogonal. If you consequently use
the correct types in your foreign declarations (i.e. CInt, CLong, CULong,
etc.) then these will be mapped to the native C types, i.e. CInt is 64-bit
iff it is 64-bit for the C compiler.

BTW, next time before you jump to conclusions you might want to consider
looking at the available documentation. The FFI spec is online at
http://www.cse.unsw.edu.au/~chak/haskell/ffi/

> [...]
> IMHO, modern FPL implementations should do as much as possible to reuse
> each others bindings. This would make them much more "safe" in practice.

It would be very nice if we could do that but I can't see how. And anyway,
creating the bindings themselves is easy (if tedious) in Haskell. The
problem is how to marshall custom C data types, and -- much  more
difficult -- how to 'adapt' the mostly very imperative C libraries to the
functional paradigm.

Cheers
Ben
0
12/20/2007 1:22:52 AM
Ben Franksen wrote:
> Jon Harrop wrote:
>> Ben Franksen wrote:
>>> What do you mean? I am completely stupefied that something like this is
>>> even possible in Haskell, with all the real-time stuff needed.
>> 
>> The real time requirements for a game like that are actually
>> comparatively easy because the game is not CPU intensive.
> 
> But it still needs to take care that whatever it does (graphical I/O,
> mostly?) completes fast enough.

Correct. However, even if Haskell were running 100x slower than C here it
would not notice.

The fact is, all of these languages (OCaml, SML, Haskell, F#) can excel at
exactly this kind of application. They are simply superb for
high-performance visualization. They already work extremely well for what
their bindings are capable of (thousands of people use LablGL, for
example). However, incomplete and poorly documented bindings to libraries
like OpenGL and GLU are really letting these languages down and this is a
great shame.

>> Frag loads data from binary formats and, to do so, it uses a lot of
>> unsafe IO calls (I assume this was done for performance: I can't think of
>> any other reason to do it).
>> 
>> However, these calls somehow assume 32-bit ints
>> and, consequently, break Frag on 64-bit machines like mine. So I can only
>> run Frag in a 32-bit chroot.
> 
> These things have /nothing/ to do with each other.
> 
> The word 'unsafe' like in
> 
>   foreign import unsafe xxyy...
> 
> means that the foreign routine is not supposed to call back into the
> Haskell world. Thus, whether a foreign import can safely be made 'unsafe'
> depends only on the semantics of the C routine. Naming this 'unsafe' is
> generally believed to be misleading. It is planned to rename it in the
> next standard to something that indicates better what it means. Using the
> 'unsafe' qualifier in a foreign import declaration is indeed done for
> efficiency reasons: an 'unsafe' call is a lot cheaper than a 'safe' one.
> 
> The 32/64 bit distinction is completely orthogonal. If you consequently
> use the correct types in your foreign declarations (i.e. CInt, CLong,
> CULong, etc.) then these will be mapped to the native C types, i.e. CInt
> is 64-bit iff it is 64-bit for the C compiler.
> 
> BTW, next time before you jump to conclusions you might want to consider
> looking at the available documentation. The FFI spec is online at
> http://www.cse.unsw.edu.au/~chak/haskell/ffi/

I'm confused. Why are you talking about the FFI and, if this code is
actually "safe", why is it segfaulting?

>> [...]
>> IMHO, modern FPL implementations should do as much as possible to reuse
>> each others bindings. This would make them much more "safe" in practice.
> 
> It would be very nice if we could do that but I can't see how.

The simplest way is to autogenerate low-level bindings using a common
intermediate representation: C headers augmented with static type
information. Then at least when I fix the shader code in GLCaml it could
also benefit the Haskell and SML communities.

Ideally, these languages would all share a safe HLVM on top of LLVM and
people would write low-level but safe bindings for the HLVM that each
language could then specialize in its own idiomatic way.

> And anyway, creating the bindings themselves is easy (if tedious) in
> Haskell. 

If it were "easy", people would have been able to do it by now. Look at the
GLU library, for example. Only ~300 lines of (commented!) C header file but
nobody has ever managed to write safe bindings to it from any
statically-typed FPL (AFAIK).

> The 
> problem is how to marshall custom C data types, and -- much  more
> difficult -- how to 'adapt' the mostly very imperative C libraries to the
> functional paradigm.

No, the problem is that people grossly underestimate how technically
difficult this is, bite off more than they can chew and never finish
anything. Essentially, the problem is that you need domain-specific
expertise in two different areas: the FFI and the library itself.

If you look at the Haskell community, for example, very few people there
have expertise outside functional programming (e.g. with OpenGL) and very
few people there have ever written anything of production quality. So the
number of people who are even theoretically capable of writing good OpenGL
bindings is basically zero. Even if they did exist, they would need a lot
of time and would almost certainly get zero recompense for their work.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/20/2007 4:20:57 PM
Jon Harrop wrote:
> Ben Franksen wrote:
>> Jon Harrop wrote:
>>> unsafe IO calls (I assume this was done for performance: I can't think
>>> of any other reason to do it).
>>> 
>>> However, these calls somehow assume 32-bit ints
>>> and, consequently, break Frag on 64-bit machines like mine. So I can
>>> only run Frag in a 32-bit chroot.
>> 
>> These things have /nothing/ to do with each other.
>> 
>> The word 'unsafe' like in
>> 
>>   foreign import unsafe xxyy...
>> 
>> means that the foreign routine is not supposed to call back into the
>> Haskell world. Thus, whether a foreign import can safely be made 'unsafe'
>> depends only on the semantics of the C routine. Naming this 'unsafe' is
>> generally believed to be misleading. It is planned to rename it in the
>> next standard to something that indicates better what it means. Using the
>> 'unsafe' qualifier in a foreign import declaration is indeed done for
>> efficiency reasons: an 'unsafe' call is a lot cheaper than a 'safe' one.
>> 
>> The 32/64 bit distinction is completely orthogonal. If you consequently
>> use the correct types in your foreign declarations (i.e. CInt, CLong,
>> CULong, etc.) then these will be mapped to the native C types, i.e. CInt
>> is 64-bit iff it is 64-bit for the C compiler.
>> 
>> BTW, next time before you jump to conclusions you might want to consider
>> looking at the available documentation. The FFI spec is online at
>> http://www.cse.unsw.edu.au/~chak/haskell/ffi/
> 
> I'm confused. Why are you talking about the FFI and, if this code is
> actually "safe", why is it segfaulting?

/You/ have been talking about FFI, so I assumed this was about the 'unsafe'
specifier in the FFI.

I checked the source code, this time. There are exactly two different
identifiers in frag that contain the word 'unsafe': the functions
unsafePreservingMatrix and unsafeRenderPrimitive. They are both from the
OpenGL binding. THis is the source code and documentation comments on them:

-- | A more efficient, but potentially dangerous version
of 'preservingMatrix':
-- The given action is not allowed to throw an exception or change the
-- current matrix mode permanently.
unsafePreservingMatrix :: IO a -> IO a
unsafePreservingMatrix = unsafeBracket_ glPushMatrix glPopMatrix

-- | A more efficient, but potentially dangerous version
of 'renderPrimitive':
-- The given action is not allowed to throw an exception.
unsafeRenderPrimitive :: PrimitiveMode -> IO a -> IO a
unsafeRenderPrimitive = renderPrim unsafeBracket_

I can't see any reason why these should cause a segfault, even if used
improperly, i.e. with code that does throw exceptions. I may be wrong, but
it seems the worst that can happen is that things aren't properly cleaned
up afterwards.

The easiest way to clarify would be to replace these calls in frag by the
safe versions and see if the segfault disappears (which I don't believe
will happen).

My best guess is that the FFI (OpenGL or GLUT) has a bug, somewhere,
assuming a C-int always has 32 bits. It has probably not been tested
thoroughly on 64-bit systems.

>>> [...]
>>> IMHO, modern FPL implementations should do as much as possible to reuse
>>> each others bindings. This would make them much more "safe" in practice.
>> 
>> It would be very nice if we could do that but I can't see how.
> 
> The simplest way is to autogenerate low-level bindings using a common
> intermediate representation: C headers augmented with static type
> information. Then at least when I fix the shader code in GLCaml it could
> also benefit the Haskell and SML communities.
> 
> Ideally, these languages would all share a safe HLVM on top of LLVM and
> people would write low-level but safe bindings for the HLVM that each
> language could then specialize in its own idiomatic way.

Hm, this seems possible. Who is going to create this common intermediate
language?

>> And anyway, creating the bindings themselves is easy (if tedious) in
>> Haskell.
> 
> If it were "easy", people would have been able to do it by now. Look at
> the GLU library, for example. Only ~300 lines of (commented!) C header
> file but nobody has ever managed to write safe bindings to it from any
> statically-typed FPL (AFAIK).

I bet I could write you a Haskell GLU binding in a few hours. But this won't
help you very much, because all the marshalling will be missing and the
interface will be exactly as imperative as in the original lib. It will
also be completely untested because I lack understanding of what GLU is
about.

>> The
>> problem is how to marshall custom C data types, and -- much  more
>> difficult -- how to 'adapt' the mostly very imperative C libraries to the
>> functional paradigm.
> 
> No, the problem is that people grossly underestimate how technically
> difficult this is, 

The C libraries may be technically difficult to handle. Maybe the problem
GLU tries to solve itself is difficult. But writing a Haskell FFI binding,
no. Not for something as small as GLU.

> bite off more than they can chew and never finish
> anything. Essentially, the problem is that you need domain-specific
> expertise in two different areas: the FFI and the library itself.

The FFI in Haskell is very straight forward. I think anyone motivated enough
to do such a binding for Haskell would find that this is the least problem.

Domain expertise is a different matter, however. I don't have it, for sure.

> If you look at the Haskell community, for example, very few people there
> have expertise outside functional programming (e.g. with OpenGL)

How do you know that?

> and very
> few people there have ever written anything of production quality.

Have you counted them? How did you find out?

> So the
> number of people who are even theoretically capable of writing good OpenGL
> bindings is basically zero.

Can you provide /any/ evidence for this claim? Have you ever contacted the
maintainer of the OpenGL bindings, for example?

> Even if they did exist, they would need a lot
> of time and would almost certainly get zero recompense for their work.

Instead of bullshiting people who have done hard work (OpenGL is /much/
larger than GLU), you could /at least/ file a decent bug report to the
OpenGL library binding maintainers. Better still, support them with your
domain specific expertise.

Cheers
Ben
0
12/22/2007 1:56:06 AM
Ben Franksen wrote:
> Jon Harrop wrote:
>> I'm confused. Why are you talking about the FFI and, if this code is
>> actually "safe", why is it segfaulting?
> 
> /You/ have been talking about FFI,

I was talking about the IO code in Frag.

> so I assumed this was about the 'unsafe' specifier in the FFI.

I meant "unsafe" as in "the [IO] code in Frag is not safe because it
segfaults".

Nothing to do with the FFI or an "unsafe" specifier.

> ...
> My best guess is that the FFI (OpenGL or GLUT) has a bug, somewhere,
> assuming a C-int always has 32 bits.

It never even gets to run OpenGL code: it segfaults whilst loading its data
from binary files.

> It has probably not been tested thoroughly on 64-bit systems.

I suspect I am the only person to have ever tried Frag on a 64-bit machine
(despite the fact that it is hailed as one of the great successes of
Haskell).

>> Ideally, these languages would all share a safe HLVM on top of LLVM and
>> people would write low-level but safe bindings for the HLVM that each
>> language could then specialize in its own idiomatic way.
> 
> Hm, this seems possible. Who is going to create this common intermediate
> language?

I'm going to try but several other people have expressed an interest in the
idea.

>>> And anyway, creating the bindings themselves is easy (if tedious) in
>>> Haskell.
>> 
>> If it were "easy", people would have been able to do it by now. Look at
>> the GLU library, for example. Only ~300 lines of (commented!) C header
>> file but nobody has ever managed to write safe bindings to it from any
>> statically-typed FPL (AFAIK).
> 
> I bet I could write you a Haskell GLU binding in a few hours. But this
> won't help you very much, because all the marshalling will be missing and
> the interface will be exactly as imperative as in the original lib. It
> will also be completely untested because I lack understanding of what GLU
> is about.

Jacques Garrigue already did exactly that for OCaml. He didn't test it
either. When I tried to use it I found that it could never have worked and
required a complete rewrite. So I rewrote it myself but I lack experience
with OCaml's FFI and could not do a good job, only something that works
well enough for my purposes which is what you'll still find in LablGL
today.

>>> The
>>> problem is how to marshall custom C data types, and -- much  more
>>> difficult -- how to 'adapt' the mostly very imperative C libraries to
>>> the functional paradigm.
>> 
>> No, the problem is that people grossly underestimate how technically
>> difficult this is,
> 
> The C libraries may be technically difficult to handle. Maybe the problem
> GLU tries to solve itself is difficult. But writing a Haskell FFI binding,
> no. Not for something as small as GLU.

You can prove that by writing working bindings to GLU for Haskell.

>> bite off more than they can chew and never finish
>> anything. Essentially, the problem is that you need domain-specific
>> expertise in two different areas: the FFI and the library itself.
> 
> The FFI in Haskell is very straight forward. I think anyone motivated
> enough to do such a binding for Haskell would find that this is the least
> problem.
> 
> Domain expertise is a different matter, however. I don't have it, for
> sure.

You cannot hope to write bindings for a library that you are totally
unfamiliar with. You will not know what high-level types should be used,
what needs to be efficient, when to weaken the type system and so on. Even
people with significant experience of OpenGL don't get the API right the
first time.

>> If you look at the Haskell community, for example, very few people there
>> have expertise outside functional programming (e.g. with OpenGL)
> 
> How do you know that?

I tried to find them only the discover that they only exist in theory.

>> and very few people there have ever written anything of production
>> quality. 
> 
> Have you counted them?

Yes, literally. We've compiled case studies of industrial applications of
all modern functional programming languages, including Haskell.

> How did you find out? 

I asked around, interviewed relevant people and spent a long time doing
market research.

The makeup of the Haskell community is very different to that of the OCaml
(and Erlang) communities but it is roughly the same size. Specifically,
OCaml and Erlang are much more widely used in industry, there is a lot more
money in the OCaml and Erlang markets and a lot more professionals sell
code written in OCaml and Erlang. There are some examples for Haskell but
they are few and far between. SML is basically dead in this respect (there
was Harlequin a long time ago but their business strategy was non-existent
so they're no longer with us).

We did this when working out which directions we could most productively
diversify into. Our conclusion was that Haskell is interesting but
impractical.

>> So the
>> number of people who are even theoretically capable of writing good
>> OpenGL bindings is basically zero.
> 
> Can you provide /any/ evidence for this claim?

I looked and couldn't find any.

> Have you ever contacted the maintainer of the OpenGL bindings, for
> example?

Don Stewart seems to have inherited the maintainence of the primary OpenGL
bindings for Haskell (and almost all other Haskell software as well). When
I asked him about the problems he simply added a note to the Haskell Wiki
page:

  "There are reports of crashes on 64 bit machines. If you have access to a
64 bit machine, with a recent OpenGL, please do consider checking the FFI
bindings for 64 bit cleanliness. 32 bit machines appear to be fine."

I can't expect Don to fix the problems or write working code, of course.
Apparently the code was lashed together by some academic student and is
completely unmaintainable.

>> Even if they did exist, they would need a lot
>> of time and would almost certainly get zero recompense for their work.
> 
> Instead of bullshiting people who have done hard work (OpenGL is /much/
> larger than GLU),

No, binding OpenGL actually requires less code than binding GLU because the
API only uses trivial types. For example, the entire GLCaml bindings to
OpenGL 2 are generated by a 676-line OCaml program but LablGL's incomplete
GLU bindings already total 720 lines.

This is exactly the kind of thing that you cannot anticipate without
domain-specific experience in this area.

> you could /at least/ file a decent bug report to the 
> OpenGL library binding maintainers. Better still, support them with your
> domain specific expertise.

I'm helping to fix GLCaml right now and am compiling working demos using it.
The best I can hope for Haskell is to make my work reusable.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/22/2007 3:36:33 AM
On Sat, 22 Dec 2007, Jon Harrop wrote:

> I suspect I am the only person to have ever tried Frag on a 64-bit machine
> (despite the fact that it is hailed as one of the great successes of
> Haskell).
> 

I don't see it described as a "great success" too often, in fact I think 
you're the first person I've seen say anything like it. It's a "we can get 
it to work", and a somewhat real-world example of FRP - in other words, 
a proof of concept.

> You cannot hope to write bindings for a library that you are totally
> unfamiliar with. You will not know what high-level types should be used,
> what needs to be efficient, when to weaken the type system and so on. Even
> people with significant experience of OpenGL don't get the API right the
> first time.
> 

Thankfully, an efficient compiler means that you can write the obvious 
low-level bindings and then build a high-level wrapper at your own 
leisure. This is exactly what's been done with gtk2hs, for example.

> >> If you look at the Haskell community, for example, very few people there
> >> have expertise outside functional programming (e.g. with OpenGL)
> > 
> > How do you know that?
> 
> I tried to find them only the discover that they only exist in theory.
> 

Funny. It's been a while, but as a kid I used to hang out in gamedev 
space - it's been quite some time since I've used any of it, but by far 
the largest problem I would have in writing an OpenGL binding for Haskell 
is simply that it's tedious.

> >> and very few people there have ever written anything of production
> >> quality. 
> > 
> > Have you counted them?
> 
> Yes, literally. We've compiled case studies of industrial applications of
> all modern functional programming languages, including Haskell.
> 

Which isn't the same thing as industrial applications written by Haskell 
programmers. I think you mean that very few people there have ever written 
anything of production quality /in Haskell/. There's a significant 
difference between that and your own statement.

-- 
flippa@flippac.org

Society does not owe people jobs.
Society owes it to itself to find people jobs.
0
flippa (196)
12/22/2007 7:17:53 PM
Philippa Cowderoy wrote:
> On Sat, 22 Dec 2007, Jon Harrop wrote:
>> I suspect I am the only person to have ever tried Frag on a 64-bit
>> machine (despite the fact that it is hailed as one of the great successes
>> of Haskell).
> 
> I don't see it described as a "great success" too often, in fact I think
> you're the first person I've seen say anything like it. It's a "we can get
> it to work", and a somewhat real-world example of FRP - in other words,
> a proof of concept.

Frag appears to be the only non-trivial OpenGL application ever written in
Haskell (and it segfaults).

>> You cannot hope to write bindings for a library that you are totally
>> unfamiliar with. You will not know what high-level types should be used,
>> what needs to be efficient, when to weaken the type system and so on.
>> Even people with significant experience of OpenGL don't get the API right
>> the first time.
> 
> Thankfully, an efficient compiler means that you can write the obvious
> low-level bindings and then build a high-level wrapper at your own
> leisure.

Have you ever written high-performance bindings to any library? Have you
ever used high-performance bindings to any library?

> This is exactly what's been done with gtk2hs, for example. 

GTK+ is not a high-performance library.

Also, are there any non-trivial programs written in gtk2hs (that work)?

>> >> If you look at the Haskell community, for example, very few people
>> >> there have expertise outside functional programming (e.g. with OpenGL)
>> > 
>> > How do you know that?
>> 
>> I tried to find them only the discover that they only exist in theory.
> 
> Funny. It's been a while, but as a kid I used to hang out in gamedev
> space - it's been quite some time since I've used any of it,

So you're not an OpenGL expert.

> but by far the largest problem I would have in writing an OpenGL binding
> for Haskell is simply that it's tedious.

Just go and try and you'll understand why what you're saying now is wrong.

>> >> and very few people there have ever written anything of production
>> >> quality.
>> > 
>> > Have you counted them?
>> 
>> Yes, literally. We've compiled case studies of industrial applications of
>> all modern functional programming languages, including Haskell.
> 
> Which isn't the same thing as industrial applications written by Haskell
> programmers. I think you mean that very few people there have ever written
> anything of production quality /in Haskell/.

No, I meant that the Haskell community is composed almost entirely of
non-professionals and academics who have never written production quality
code in any language.

> There's a significant difference between that and your own statement.

Sure.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/22/2007 8:55:03 PM
On Sat, 22 Dec 2007, Jon Harrop wrote:

> Philippa Cowderoy wrote:
> > On Sat, 22 Dec 2007, Jon Harrop wrote:
> >> I suspect I am the only person to have ever tried Frag on a 64-bit
> >> machine (despite the fact that it is hailed as one of the great successes
> >> of Haskell).
> > 
> > I don't see it described as a "great success" too often, in fact I think
> > you're the first person I've seen say anything like it. It's a "we can get
> > it to work", and a somewhat real-world example of FRP - in other words,
> > a proof of concept.
> 
> Frag appears to be the only non-trivial OpenGL application ever written in
> Haskell (and it segfaults).
> 

I can't help but point out that rendering Quake 3 maps and models without 
shaders on modern hardware is also pretty trivial by the standards I've 
been used to. I won't say all the cool kids were doing it four years back 
- half couldn't be bothered. It wasn't that uncommon as a learning 
project. It tended to bring home to people the difference between a 3D 
engine and a game engine when they went on to write an actual game.

Looking at the code, the segfaulting IO is probably because it makes 
assumptions about the size of CInt etc rather than using more appropriate 
types. It probably has endian issues too. I've updated the wiki page to 
reflect this.

http://www.cas.mcmaster.ca/~kahl/3DGraphs/

> >> You cannot hope to write bindings for a library that you are totally
> >> unfamiliar with. You will not know what high-level types should be used,
> >> what needs to be efficient, when to weaken the type system and so on.
> >> Even people with significant experience of OpenGL don't get the API right
> >> the first time.
> > 
> > Thankfully, an efficient compiler means that you can write the obvious
> > low-level bindings and then build a high-level wrapper at your own
> > leisure.
> 
> Have you ever written high-performance bindings to any library? Have you
> ever used high-performance bindings to any library?
> 

Have you ever used an FFI that allows you to write almost exactly 
the equivalent of the appropriate C code in the language in question? The 
obvious low-level binding in Haskell sidesteps the issues entirely, 
leaving marshalling concerns to the user (who may well just choose to 
work with C-style types manipulated via the IO monad throughout).

Naturally there's the worry of function call overhead (though I understand 
it's pretty cheap in the unthreaded RTS). I don't think either of us is 
going to be calling glVertex3f for performance any time soon though, so 
this is unlikely to be the bottleneck.

No, this isn't the safe binding you have in mind. I didn't claim it was 
either.

> > This is exactly what's been done with gtk2hs, for example. 
> 
> GTK+ is not a high-performance library.
> 
> Also, are there any non-trivial programs written in gtk2hs (that work)?
> 

Yi has a gtk-based UI available - I've not tried it though, the build 
process isn't fun under Windows (this isn't gtk2hs's fault though, I've 
had gtk2hs apps working easily enough). IIRC the Epigram crowd are using 
it for their WIP editor as well, though I imagine you'd consider that too 
academic. I'm aware of there being other users generally, but don't have 
citations to hand.

> >> >> If you look at the Haskell community, for example, very few people
> >> >> there have expertise outside functional programming (e.g. with OpenGL)
> >> > 
> >> > How do you know that?
> >> 
> >> I tried to find them only the discover that they only exist in theory.
> > 
> > Funny. It's been a while, but as a kid I used to hang out in gamedev
> > space - it's been quite some time since I've used any of it,
> 
> So you're not an OpenGL expert.
> 

I'm not any more, I'm too far out of date and I'm just not using the 
knowledge for anything these days - but I got well past the point of 
answering other people's questions. I know what to look up if I 
want to sling triangles quickly though, just don't ask me about shaders. I 
definitely wouldn't have a technical problem producing enough binding to 
reproduce something like Frag.

> > but by far the largest problem I would have in writing an OpenGL binding
> > for Haskell is simply that it's tedious.
> 
> Just go and try and you'll understand why what you're saying now is wrong.
> 

I'm afraid the issues you're talking about would have to be really rather 
major to overrule the tedium, unfortunately. I don't doubt that writing a 
really nice high-level, safe wrapper that interacts nicely with at least 
one safe array type is going to require some thought. I just don't have to 
do it to have a working binding.

> >> >> and very few people there have ever written anything of production
> >> >> quality.
> >> > 
> >> > Have you counted them?
> >> 
> >> Yes, literally. We've compiled case studies of industrial applications of
> >> all modern functional programming languages, including Haskell.
> > 
> > Which isn't the same thing as industrial applications written by Haskell
> > programmers. I think you mean that very few people there have ever written
> > anything of production quality /in Haskell/.
> 
> No, I meant that the Haskell community is composed almost entirely of
> non-professionals and academics who have never written production quality
> code in any language.
> 

And that's a statement I highly doubt you're qualified to make. It's true 
of a significant proportion of those of us who're more visible, sure. A 
good many of Haskell's professional uses aren't publically available 
though and I strongly doubt you're running a full background check on 
everyone who comes to light as being part of the community. Plenty of 
people in #haskell are non-academics and code for their living.

-- 
flippa@flippac.org

A problem that's all in your head is still a problem.
Brain damage is but one form of mind damage.
0
flippa (196)
12/22/2007 11:13:57 PM
Philippa Cowderoy wrote:
> On Sat, 22 Dec 2007, Jon Harrop wrote:
>> Have you ever written high-performance bindings to any library? Have you
>> ever used high-performance bindings to any library?
> 
> Have you ever used an FFI that allows you to write almost exactly
> the equivalent of the appropriate C code in the language in question?

Yes, F# does that.

> The 
> obvious low-level binding in Haskell sidesteps the issues entirely,
> leaving marshalling concerns to the user

That doesn't make sense. What you're calling "marshalling" is almost the
only issue so leaving it to the user is not sidestepping anything of
importance.

> (who may well just choose to work with C-style types manipulated via the
> IO monad throughout). 

How efficient is that?

> Naturally there's the worry of function call overhead (though I understand
> it's pretty cheap in the unthreaded RTS). I don't think either of us is
> going to be calling glVertex3f for performance any time soon though, so
> this is unlikely to be the bottleneck.

Right, the issue is making efficient use (for example) of vertex buffer
objects allocated in AGP memory directly from your FPL when the data
structure is an array of structs of structs including 16-bit ints and
32-bit floats.

>> Also, are there any non-trivial programs written in gtk2hs (that work)?
> 
> Yi has a gtk-based UI available - I've not tried it though, the build
> process isn't fun under Windows (this isn't gtk2hs's fault though, I've
> had gtk2hs apps working easily enough).

I can't find any usage information for Yi: it doesn't seem to have packages
for major Linux distros.

> IIRC the Epigram crowd are using 
> it for their WIP editor as well, though I imagine you'd consider that too
> academic.

Looks like Epigram is a research prototype compiler for a Haskell derivative
with basically zero users.

> I'm not any more, I'm too far out of date and I'm just not using the
> knowledge for anything these days - but I got well past the point of
> answering other people's questions. I know what to look up if I
> want to sling triangles quickly though, just don't ask me about shaders. I
> definitely wouldn't have a technical problem producing enough binding to
> reproduce something like Frag.

Sure but that's about a decade out of date now.

>> > but by far the largest problem I would have in writing an OpenGL
>> > binding for Haskell is simply that it's tedious.
>> 
>> Just go and try and you'll understand why what you're saying now is
>> wrong.
> 
> I'm afraid the issues you're talking about would have to be really rather
> major to overrule the tedium, unfortunately.

Look at the GLCaml bindings for OCaml, for example. They are autogenerated
by <700 lines of OCaml code. Is that really so tedious?

> I don't doubt that writing a 
> really nice high-level, safe wrapper that interacts nicely with at least
> one safe array type is going to require some thought. I just don't have to
> do it to have a working binding.

That depends what you mean by "working". If I bind a single function call
and don't test it, have I created "working" bindings? Or must I handle
dynamic loading of OpenGL calls, the extension system and write
comprehensive examples to test it?

>> No, I meant that the Haskell community is composed almost entirely of
>> non-professionals and academics who have never written production quality
>> code in any language.
> 
> And that's a statement I highly doubt you're qualified to make. It's true
> of a significant proportion of those of us who're more visible, sure. A
> good many of Haskell's professional uses aren't publically available
> though and I strongly doubt you're running a full background check on
> everyone who comes to light as being part of the community. Plenty of
> people in #haskell are non-academics and code for their living.

Very well. All I can say is that finding industrial uses and users of OCaml
and F# has been much easier.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/23/2007 1:58:27 AM
Jon Harrop wrote:
> Very well. All I can say is that finding industrial uses and users of OCaml
> and F# has been much easier.

Perhaps Haskell users have better taste in consultants?



(No offense to *ML users, except the ones with poor taste in consultants.)
0
anton58 (1240)
12/23/2007 11:15:29 AM
Anton van Straaten wrote:
> Jon Harrop wrote:
>> Very well. All I can say is that finding industrial uses and users of
>> OCaml and F# has been much easier.
> 
> Perhaps Haskell users have better taste in consultants?

Then where are the products and services advertised?

Can you find a single end-user product written in Haskell?

Here is the "Haskell in Industry" page:

  http://haskell.org/haskellwiki/Haskell_in_industry

That page lists 12 industrial users of Haskell and its author
states "they're the big players, there's numerous small groups that have
maybe a few in house Haskell tools.".

Of those 12 big players, can you find any references to any of them
currently using Haskell except for the three financial users and Galois?
One of them is "Erlang training and consulting", for example.

The only person who seems to be really trying to sell Haskell to the world
is Donald Bruce Stewart. Look at his post about the Haskell job market
coming to life:

  http://cgi.cse.unsw.edu.au/~dons/blog/2007/11/24

and note the jobs are all OCaml/F# and not Haskell.

There are seven current jobs posted on:

  http://haskell.org/haskellwiki/Jobs

of which four are academic positions, one is prototyping an F# program in
Haskell, one is actually in Ruby and the other is from the financial
sector.

In summary:

.. No Haskell products except for books targetted at academics.
.. Few Haskell services offered.
.. Few jobs in industry.

What would you conclude?

Open source projects written in OCaml that are otherwise unrelated to OCaml
have tens of thousands of users (the ocaml-base-nox package has 14,000
registered installs on Debian and Ubuntu, for example), many more than
anything written in Haskell AFAICT. Is this related to Haskell's
relatively-slow uptake in industry for application programming?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
0
usenet116 (1778)
12/23/2007 4:23:48 PM
Lauri Alanko <la@iki.fi> wrote:
> In article <fhaoou$nfq$1@oravannahka.helsinki.fi>,
> Vesa Karvonen  <vesa.karvonen@cs.helsinki.fi> wrote:
> > > > sgn :: Int -> Int
> > > > sgn x | x > 0   = 1
> > > > sgn x | x < 0   = -1
> > > > sgn _           = 0
> >
> > > Ah, but that is the very worst thing you can do. In the name of
> > > satisfying exhaustiveness checking (and perhaps also in the name of
> > > efficiency),
> >
> > Nope.  The real motivation is neither exhaustiveness checking nor
> > efficiency.  The motivation is just to avoid unnecessary verbosity.

> Your transformation amounts to removing an assertion check. [...]

Yes, it amounts to removing a *redundant* assertion check that is
statically known never to fail.

> > Comparing against zero is redundant here, because there are no
> > integers other than 0 that are neither less than nor greater than 0.

> [...] a programmer is fallible, and must take her fallibility into
> account in her code.

I'm against "defensive programming" as described by Bertrand Meyer.
Briefly, what Meyer dubs as "defensive programming" (there are other
meanings for the term) basically amounts to ad hoc redundant /
repeated
checking of invariants.  Your code essentially checks the invariant
redundantly.  The type constraint in the code makes the check
redundant.

You code is analogous to having a function that takes a Maybe value
explicitly checking at run-time that the value is either a Nothing or
a
Just.  Such a check is redundant (well, at least in a strict
language).

> If your refutation of my example is not generalizable, then what
> exactly do you intend to achieve with it?

Your assumption is false, because my refutation can be generalized to
all
cases where a check is known to be redundant (due to earlier checks
and
static type information).  OTOH, your programming style is arguably
non-generalizable.  If taken to its full conclusion, it amounts to
repeatedly and redundantly checking properties that are already known
to
be enforced.  Examples of such programming style have been presented
on
The Daily WTF.

> My original point was to demonstrate that a pattern-matching function
> can be total even though the exhaustiveness checker cannot prove that
> it is. For this my example function was suitable.

A function may, of course, be total even if it cannot be proven by an
exhaustiveness checker.  I object to your example, because it foils
simple
exhaustiveness checking by adding a redundant check.  IOW, I find that
it
is a contrived example that uses a programming style, namely defensive
programming, that does not generalize, because it amounts to adding
strictly redundant checks to the program.

> [...] in this particular case I believe that the danger doesn't get
> actualized.

We both know that, assuming a correct Haskell implementation, there is
no
danger in this case.

> Let's try again, with a slight variation. Let's write a function:

> sgn :: Double -> Double
> sgn x |  x < 0  = -1
> sgn x | x == 0  =  0
> sgn x |  x > 0  =  1

Here I would argue that the type of the function is wrong.  A better
way
to write the above would be to introduce a new type, say, DoubleNum,
whose
values are statically known to be numbers and never NAN.  (This would
make
the last guard redundant.)

Let's hope that we don't see the above code in a pacemaker!

-Vesa Karvonen
0
1/2/2008 3:48:12 PM
Vesa.A.J.K@gmail.com writes:
> > sgn :: Double -> Double
> > sgn x |  x < 0  = -1
> > sgn x | x == 0  =  0
> > sgn x |  x > 0  =  1
> 
> Here I would argue that the type of the function is wrong. ...

Oh my.  From GHCI 6.4.2:

    Prelude> :t compare
    compare :: (Ord a) => a -> a -> Ordering
    Prelude> compare 2 3
    LT
    Prelude> let x = 0/0
    Prelude> x
    NaN
    Prelude> compare 2 x
    GT
    Prelude> compare x 2
    GT
    Prelude> compare x x
    GT
0
phr.cx (5493)
1/2/2008 8:18:54 PM
Paul Rubin <http://phr.cx@nospam.invalid> wrote:
> Vesa.A.J.K@gmail.com writes:
> > > sgn :: Double -> Double
> > > sgn x |  x < 0  = -1
> > > sgn x | x == 0  =  0
> > > sgn x |  x > 0  =  1
> > 
> > Here I would argue that the type of the function is wrong. ...

> Oh my.  From GHCI 6.4.2:

>     Prelude> :t compare
>     compare :: (Ord a) => a -> a -> Ordering
>     Prelude> compare 2 3
>     LT
>     Prelude> let x = 0/0
>     Prelude> x
>     NaN
>     Prelude> compare 2 x
>     GT
>     Prelude> compare x 2
>     GT
>     Prelude> compare x x
>     GT

I honestly can't say that I would be surprised.  Almost every language
starting with C is designed to produce meaningless results in order to
look good on toy benchmarks.  SML is one of the few exceptions.  As a case
in point, the corresponding SML code raises an exception:

Standard ML of New Jersey v110.66 [built: Thu Nov 15 12:22:47 2007]
- Real.compare ;
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val it = fn : real * real -> order
- val x = 0.0/0.0 ;
val x = nan : real
- Real.compare (2.0, x) ;

uncaught exception Unordered
  raised at: Basis/Implementation/real64.sml:149.13-149.31

See these:

  http://www.standardml.org/Basis/real.html#SIG:REAL.sign:VAL
  http://www.standardml.org/Basis/real.html#SIG:REAL.compare:VAL

-Vesa Karvonen
0
1/2/2008 8:36:32 PM
Reply: