Re: F#

2007-11-11 Thread David MacIver

On Nov 11, 2007 3:34 PM, David MacIver [EMAIL PROTECTED] wrote:
  Per-function type annotations are considered good practice in Haskell 
  because
  it has an undecideable type system but not in ML, where you generally see no
  type annotations whatsoever.

 Haskell's core type system isn't undecidable as far as I know. Type
 inference is entirely possible and no less straightforward than in ML
 with Haskell's core Hindley Milner + type classes type system. It's
 more a case of readability and explicit public contracts for the
 module. Haskell's type system + a bazillion add-ons found only in GHC
 head is of course. ;-)

Sorry, talking at cross purposes (and I made a mistake). Type
*checking* for the core type system is decidable. Type inference isn't
(e.g. show(read 1) needs a type annotation).

In general I'm willing to live with features that can't be inferred as
long as a large enough subset of the language can be. Adding explicit
type annotations for features which allow more expresivity doesn't
strike me as an unreasonable trade off.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups JVM 
Languages group.
To post to this group, send email to jvm-languages@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~--~~~~--~~--~--~---



Re: F#

2007-11-11 Thread Jon Harrop

On Sunday 11 November 2007 15:34, David MacIver wrote:
 On Nov 11, 2007 1:54 PM, Jon Harrop [EMAIL PROTECTED] wrote:
  Explicit types also have disadvantages. I think it is only fair to
  consider both approaches.

 Certainly. I'm perfectly willing to consider implicit types as a
 valuable thing. But it's an independent discussion.

Ah, ok. I think you will have trouble distinguishing between inferred sum 
types and extensible sum types in OCaml because they are provided by the same 
construct. Indeed, the inference is an integral part of their extensibility.

  The ML family of languages basically is OCaml and F# now:

 I'm sure that will come as news to the people working on MLTon, Alice,
 SML/NJ...

I doubt it. SML/NJ is the most popular SML compiler and has never been updated 
to support x86-64. MLton is also popular but has only rudimentary support for 
x86-64, with poor performance and regular segfaults. We sell more books on 
OCaml than all SML books combined. The OCaml mailing lists have had 7,000 
posts this year whereas .

  http://ocamlnews.blogspot.com/2007/11/most-popular-functional-languages-o
 n.html

 That's using a rather specific metric. I rarely use apt for language
 runtimes/compilers I actually care about because it's usually a few
 versions behind.

There would have to be thousands of people installing MLton from source but 
not OCaml from source for that to be significant. I doubt that is the case. 
In fact, I suspect OCaml's lead is larger than those results indicate because 
most SML programmers will have more than one of SMLNJ, MLton and MosML 
installed.

   ...
   Nice requires explicit packages for everything. This is a Java
   interoperability issue.
 
  Ok. Do any languages offer multiple dispatch without this baggage?

 Do I need to jump up and down and shout 'CLOS' a few more times? :-)
 There are a wide variety of multiple dispatch object systems for
 Scheme as well. Clojure appears to offer one, but I don't know what
 its approach to packages is. In general, multiple dispatch seems
 rather popular in the Lisp world.

 If you want a statically typed version there's also Needle (
 http://www.nongnu.org/needle/ ), but I've never used it and the
 project seems mostly dead, and Jazz ( http://www.exalead.com/jazz/ ),
 which I don't know the current state of.

 In general there really is a lack of a good language which combines
 these features and is actually still alive. My conjecture is that this
 is because the OO fans go Eww, multiple dispatch! Give me single
 dispatch or give me death!, the FP people go Weird. It looks like
 pattern matching but... different and the Lispers go Oh noes! Itth
 thtatically typed! Run!. :-) It's a style which sits in an odd middle
 ground that hasn't got much attention.

LOL. Interesting perspective. :-)

  !T String f(Expr!T t) = toString(t);
  override !T String f(Add!T t) = ( toString(t) );
 
  The first of those two lines is equivalent to my catchall pattern.

 Right. The catch alls translate to a default implementation which
 others override.

That makes sense.

   Here's a translation of the Nice code.
   ...
   // Differentiation of expressions.
   Expr'a diff(Expr'a v, 'a x); // Type parameters are now implicit,
   indicated by starting with '.
 
  You seem to be using both overloading and type inference. I do not
  believe that is possible.

 The return types can be inferred because the function is an override
 (you still need to specify the return type of the top level version).
 The rest can't. The implicit type parameters aren't inferred - it's
 just that 'a introduces a new type parameter where it's not already in
 scope. It's just syntactic sugar.

Ok.

   `*` (Expr'a x, Int'a 0) = Int 0; // Still have to repeat this. :(
 
  In general, you will have to factor out these arbitrarily-complicated
  repeated expressions into separate functions.

 Yes, I think that's probably the case. See comments about how adding
 some form of pattern matching on top of this would probably be really
 useful.

Right. This is all about or-patterns. Vanilla SML doesn't have or-patterns and 
that is another reason why I prefer OCaml.

   `*` (Expr'a x, Mult'a u v) = (x * u) * v;
 
  This is relying upon the ability to destructure one level only, right?

 There's in principle no reason why you can't nest this arbitrarily.
 It's just that the implementation gets more complicated. This code
 didn't seem to need it.

I think if you do generalize that then you literally have pattern matching.

  The original 40 vs 5 line comparison.

 Ok. But the Nice example is significantly closer. The pseudocode (of
 which about 70% can be mechanically translated into Nice and the
 remainder requires some more intelligent compilation). The original
 code was basically Java. If you're going to argue that Java is more
 verbose than OCaml I don't think you'll gain much except a chorus of
 agreement. :-)

:-)

  If all sum types are open then you cannot provide static 

Re: F#

2007-11-10 Thread David MacIver

On Nov 10, 2007 1:33 PM, Jon Harrop [EMAIL PROTECTED] wrote:


 On Saturday 10 November 2007 04:33, hlovatt wrote:
  public interface Exp extends MultipleDispatch { Exp d( Var x ); }
 
  public abstract class AbstractExp implements Exp {
public final Exp d( Var x ) { return null; } // Body replaced by
  PEC!
public final static Exp d( Var v, Var x ) { return v == x ? new
  Lit( 1 ) : new Lit( 0 ); }
public final static Exp d( Lit l, Var x ) { return new Lit( 0 ); }
public final static Exp d( Add a, Var x ) { return new
  Add( a.left.d( x ), a.right.d( x ) ); }
public final static Exp d( Mul m, Var x ) { return new Add( new
  Mul( m.left, m.right.d( x ) ), new Mul( m.right, m.left.d( x ) ) ); }
  }
 
  public class Var extends AbstractExp {
public final String name;
public Var( String name ) { this.name = name; }
public String toString() { return name; }
  }
 
  public class Lit extends AbstractExp {
public final double value;
public Lit( final double value ) { this.value = value; }
public String toString() { return Double.toString( value ); }
  }
 
  public class Add extends AbstractExp {
public final Exp left;
public final Exp right;
public Add( Exp left, Exp right ) {
  this.left = left;
  this.right = right;
}
public String toString() { return left +  +  + right; }
  }
 
  public class Mul extends AbstractExp {
public final Exp left;
public final Exp right;
public Mul( Exp left, Exp right ) {
  this.left = left;
  this.right = right;
}
public String toString() { return left +  *  + right; }
  }

 I cannot see why you would prefer the above 40 lines of code to the 5 line
 equivalent in OCaml:

I think you're conflating two issues. Yes, OCaml's variants are quite
nice (or at least they look it. I only know the subset of OCaml that
looks behaves more or less like SML), but they're neither neccessary
nor sufficient for pattern matching. A fairer comparison would be
between multiple dispatch and pattern matching on explicitly named
types.

Also, with all due respect to PEC, it's not really a good example of
multiple dispatch - it's Java with multiple dispatch tacked on. So,
here's the corresponding Nice code:

package expression;

// We don't need to declare this, but it will help for type safety.
interface Expr!T { }

// Expression types. Note that we do have to declare fields. It would be neat if
// we could extend tuples and get the advantages of destructuring bind
on top of
// multiple dispatch, but Nice doesn't allow that.
class Add!T implements Expr!T{
  Expr!T fst;
  Expr!T snd;
}

class Mult!T implements Expr!T{
  Expr!T fst;
  Expr!T snd;
}

class Int!T implements Expr!T{
  int i;
}

class Var!T implements Expr!T{
  T t;
}

// Syntactic nicety
!T Expr!T `+` (Expr!T fst, Expr!T snd) = new Add(fst : fst, snd : snd);
!T Expr!T `*` (Expr!T fst, Expr!T snd) = new Mult(fst : fst, snd : snd);
!T Expr!T int(int i) = new Int(i : i);

// Differentiation of expressions.
// I swear there's a way to omit both the 'override' and the return
types for the overridden methods
// but I can't figure out how the syntax interacts with declaring type
parameters. :-/
!T Expr!T diff(Expr!T v, T x);
override !T Expr!T diff(Var!T v, T x) = int(x == v.t ? 1 : 0);
override !T Expr!T diff(Int!T v, T x) = new Int(i : 0);
override !T Expr!T diff(Mult!T v, T x) = v.fst * diff(v.snd, x)
+ diff(v.fst, x) * v.snd;
override !T Expr!T diff(Add!T v, T x) = diff(v.fst, x) + diff(v.snd, x);

   let rec d f x = match f with
   | `Var y when x=y - `Int 1
   | `Int _ | `Var _ - `Int 0
   | `Add(f, g) - `Add(d f x, d g x)
   | `Mul(f, g) - `Add(`Mul(f, d g x), `Mul(g, d f x))

 You have added a toString() function. However, it is broken: you need to
 bracket according to precedence. Doing this correctly is actually quite an
 interesting exercise as well. Here is an OCaml implementation:

   open Printf;;
   let rec string_of () = function
 | `Var x - x
 | `Int n - sprintf %d n
 | `Add(f, g) - sprintf %a + %a string_of f string_of g
 | `Mul(f, g) - sprintf %a %a string_of_mul f string_of_mul g
   and string_of_mul () = function
 | `Add(f, g) as e - sprintf (%a) string_of e
 | e - string_of () e;;

 How does that translate?

// I'm pretty sure it should be possible to declare f inside the
toString method for Mult (which is the only place it's used),
// but once again I can't figure out the syntax.
!T String f(Expr!T t) = toString(t);
override !T String f(Add!T t) = ( toString(t) );

!T String toString (Int!T i) = toString(i.i);
!T String toString (Var!T v) = toString(v.t);
!T String toString (Mult!T m) = f(m.fst) + f(m.snd);

Some things of note:

a) There are various language problems here, and various places where
it's clumsier than it should be. These are mostly unrelated to the
multiple dispatch. Some of them are Nice being clumsy, some of them
are me being really rusty at the language.
b)  Nice doesn't do 

Re: F#

2007-11-09 Thread David MacIver

On Nov 7, 2007 10:00 AM, Jon Harrop [EMAIL PROTECTED] wrote:

 On Wednesday 07 November 2007 05:21, hlovatt wrote:
  Therefore multiple dispatch provides the best of both worlds...

No one seems to have replied, so I thought I would. IANAExpert
disclaimers here. :-) Hopefully this will inspire someone who is to
clarify...

 Does multiple dispatch provide static checking of exhaustiveness and

It can do. Take a look at the ML-sub type system for an example of an
extension of Hindley-Milner with subtyping and multiple dispatch. The
JVM language Nice (almost) implements an extensions of this system. I
don't remember the exact mechanism which it uses to do so, but I seem
to recall it working pretty well.

On the other hand, most multiple dispatch implementations are lispy so don't.

 redundancy, and optimizing pattern match compilation via decision trees with


Certainly. There are some really heavily optimised CLOS implementations.

 the usual pattern matching features (or-patterns, guards and so on)?

I don't know.

 Also, what are the source code equivalents to the examples I posted?

I'd need to think about it. I've not written any Nice in way too long.
It would probably be somewhere in between the two in terms of
verbosity. In particular there are no implicit sum types. You'd need
to define an abstract interface (similar to a Haskell type class) or
something.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups JVM 
Languages group.
To post to this group, send email to jvm-languages@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~--~~~~--~~--~--~---



Re: F#

2007-11-05 Thread davewebb



 In the end, there may be more aspects of Scala that I consider to
 be sub-optimal design decisions.


Jon,

By sub-optimal design decisions, do you mean sub-optimal in the
context of what Scala is actually trying to be, or sub-optimal in the
context of what you'd like Scala to be? I can understand that someone
coming to Scala from an OCaml background might be missing some of the
aspects of OCaml and choose to stay clear of Scala on that basis (and
it's a good education for me to see where OCaml can express things
more elegantly - thanks). But the Scala team aren't trying to create a
new OCaml. They're trying to create a language that integrates well
into the Java ecosystem with a lot of functional features. The phrase
'sub-optimal' has got to be qualified with a context.

Regards,
Dave Webb


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups JVM 
Languages group.
To post to this group, send email to jvm-languages@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~--~~~~--~~--~--~---



Re: F#

2007-11-01 Thread Matt Hellige

On Nov 1, 10:01 pm, Jon Harrop [EMAIL PROTECTED] wrote:
 Could a CAML derivative language for the JVM gain the same traction that F# is
 gaining on .NET?

Perhaps if someone invested the same amount of money in it... (I guess
that's a bit cynical, but only a bit.)

Matt


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups JVM 
Languages group.
To post to this group, send email to jvm-languages@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~--~~~~--~~--~--~---



Re: F#

2007-11-01 Thread John Cowan

F# was a research project.  I doubt there would be enough research-fu
in just doing it again for the JVM, which is after all very similar.

On 11/1/07, Matt Hellige [EMAIL PROTECTED] wrote:

 On Nov 1, 10:01 pm, Jon Harrop [EMAIL PROTECTED] wrote:
  Could a CAML derivative language for the JVM gain the same traction that F# 
  is
  gaining on .NET?

 Perhaps if someone invested the same amount of money in it... (I guess
 that's a bit cynical, but only a bit.)

 Matt


 



-- 
GMail doesn't have rotating .sigs, but you can see mine at
http://www.ccil.org/~cowan/signatures

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups JVM 
Languages group.
To post to this group, send email to jvm-languages@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~--~~~~--~~--~--~---