Re: F#
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#
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#
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#
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#
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#
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#
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 -~--~~~~--~~--~--~---