News for hackers. Stuff that matters.
Re:My experience rewriting Enjarify in Rust by catnaroek on Monday September 19, 2016 @10:05AM (#12531519)
Rust has both “essential verbosity” and “accidental verbosity”:

(0) Lifetimes have to be represented in the language's syntax somehow, and this can't be avoided. Lifetime elision makes this a nonissue, anyway.

(1) Rust's syntax for function declarations is horrendous. In a single place, it does two things that ought to be kept separate: state the type of the function and give names to the function's arguments. This by no means essential, e.g., Haskell does this much better.

(2) The lack of global type inference really hurts when you write functions with syntactically large argument and/or return types. AFAICT, Rust's type system is Haskell's minus HKTs plus higher-ranked lifetimes. Most Rust code doesn't use anything higher-ranked, so Rust could have much more aggressive type inference. The only impediment is the Java-like syntax for method calls: you can't infer nominal object types from how objects are used. This is again purely accidental.

Re:My experience rewriting Enjarify in Rust by masklinn on Monday September 19, 2016 @10:35AM (#12531732)
> This is again purely accidental.

WRT 2 and 3, disabling/not doing global type inference was a wilful choice, Rust's designers specifically decided not to do that and to keep type inference local.

Not splitting signatures out of function declarations comes from the same place, having removed GTI there was no point in making type signatures and function declarations independent, and it provides for uniform declaration when there's no function/method body ("abstract" trait methods, extern declarations).

Re:My experience rewriting Enjarify in Rust by catnaroek on Monday September 19, 2016 @10:37AM (#12531744)
Willful or not, it makes the language more verbose.
Re:My experience rewriting Enjarify in Rust by masklinn on Monday September 19, 2016 @10:43AM (#12531787)
I don't think it does, other syntactic decisions (e.g. C++/Java-style generic declarations, reference sigils) might, or at least make the language seem noisier, but with respect to function type declarations you'd get the exact same verbosity (in terms of tokens or characters), just split differently e.g.

    fn class(&mut self, s: &'a bstr) -> u16
versus

    class :: &mut, &'a bstr -> u16
    fn class(self, s)
all you get is repeating the function name.
Re:My experience rewriting Enjarify in Rust by catnaroek on Monday September 19, 2016 @10:43AM (#12531792)
Think about `where` clauses.
Re:My experience rewriting Enjarify in Rust by masklinn on Monday September 19, 2016 @10:46AM (#12531806)
Where clauses don't go away and their verbosity doesn't change.
Re:My experience rewriting Enjarify in Rust by catnaroek on Monday September 19, 2016 @10:47AM (#12531824)
Trait constraints in Rust are syntactically more annoying than type class constraints are in Haskell. This is in spite of the fact that, semantically, both are exactly the same thing.
Re:My experience rewriting Enjarify in Rust by valarauca1 on Monday September 19, 2016 @11:44AM (#12532299)

      This is in spite of the fact that, semantically, both are exactly the same thing.
Semantics is not practice.

Rust is a compiled language. All Types/TypeClasses have to eventually be resolved down to concrete structures/tuples that can be statically or dynamically dispatched too, and in most cases allocated to the heap/stack.

Haskell is NOT a compiled language. It compiles to a bytecode that is ran by the RTS (Run Time System) a ball of ~50,000SLOC in C/C++. Haskell TypeClasses are MAGIC managed by the run-time. They are not resolved to actual machine code. A compiled Haskell program is just the bytecode+source code+compiler+RTS bundled into an ELF. Yes some Haskell is translated into pure C, but all of it can't be. The pure C Haskell still depends on the run time heavily. Especially for managing type class dynamic dispatch.

Re:My experience rewriting Enjarify in Rust by catnaroek on Monday September 19, 2016 @01:07PM (#12532917)
> All Types/TypeClasses have to eventually be resolved down to concrete structures/tuples that can be statically or dynamically dispatched too, and in most cases allocated to the heap/stack.

My original remark was strictly about surface syntax issues (verbosity). Surface syntax is handled by the compiler's front-end. I have no idea why this should affect the compiler's backend or the runtime system. But maybe you know something about compilers that I don't.

> Haskell TypeClasses are MAGIC managed by the run-time.

No. Haskell's type classes and constraints are typically implemented as vtables (although Haskellers normally call them “dictionaries”) and extra function arguments, which are resolved at compile time. (With higher-rank types, the compiler can determine that a given vtable has to be passed around between places, though.) The runtime system has no special support for type classes - a type class instance is a record (of methods) just like any other.

Of course, Rust monomorphizes generic functions, and optimizes away the intermediate step of fetching methods from vtables whenever possible. But if you use trait objects (akin to Haskell's existentials), vtables will still be there.

Re:My experience rewriting Enjarify in Rust by tome on Monday September 19, 2016 @11:49AM (#12532329)
> Haskell is NOT a compiled language

Yes it is

> It compiles to a bytecode that is ran by the RTS

Nope, it's compiled to machine code.

(We're talking about GHC here, of course)

Re:My experience rewriting Enjarify in Rust by valarauca1 on Monday September 19, 2016 @12:32PM (#12532655)
Read the GHC's docs because they disagree with you.

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Interpr...

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage...

https://hackage.haskell.org/package/vacuum

https://research.microsoft.com/en-us/um/people/simonpj/paper...

https://research.microsoft.com/en-us/um/people/simonpj/Paper...

Haskell is a complex hybrid. TypeClasses can't always be resolved to concrete statically sized types, Haskell does RTS Magic for you when this happens. Rust throws a compiler error in this case.

Re:My experience rewriting Enjarify in Rust by jerf on Monday September 19, 2016 @01:32PM (#12533112)
Implementing an abstraction that requires indirection at runtime does not traditionally render the language "not compiled". Any definition of "not compiled" that includes the vast majority of real-world C++ is not a definition in common use.

If you want to point out that "compiled" really ought to be a continuum rather than a binary property, and that by this definition Rust is "more" compiled than Haskell, I'll be right there with you (though the pre-existing word "static" probably fits better), but we'd be creating an idiosyncratic definition not shared by very many people. (Though perhaps it should be. The binary distinction of the ~1970s really isn't that useful anymore, in a world of scripting languages, JITs, and a greater focus on the costs of indirection.)

Re:My experience rewriting Enjarify in Rust by the_why_of_y on Monday September 19, 2016 @02:14PM (#12533422)
Haskell type classes are by no means magic and the run-time does absolutely nothing with them.

Type classes are de-sugared in the compiler and turned into an extra function parameter that is a record of functions, aka "dictionary".

This is a bit similar to vtables in C++, but different because firstly, the C++ vtable is already reachable from explicit parameters/implicit "this", and secondly, C++ actually has dynamic dispatch whereas type classes are not dynamic dispatch, at least from a language point of view - they essentially correspond to "overloading" in C++.

Type classes could just as well be implemented by expanding all invocations of the function with different instances and generating monomorphic code for every combination of instances. Compilers don't do that because it would waste too much space.

Also, what exactly is a "compiled language"? The words don't mean much of significance.

Re:My experience rewriting Enjarify in Rust by catnaroek on Monday September 19, 2016 @02:35PM (#12533605)
> This is a bit similar to vtables in C++, but different because firstly, the C++ vtable is already reachable from explicit parameters/implicit "this"

Rust vtables aren't attached to all objects, but they're always attached to trait objects (whose methods are dynamically dispatched). So it's halfway between C++ and Haskell in this regard.

FWIW, I would call dictionaries “vtables”. C++ and Rust just happen to impose restrictions on how vtables can be used, so that each trait object can be bundled with its own vtable (`exists a. C a => a`), rather than potentially bundling several objects with the same vtable (`exists a. C a => T a`). But this doesn't mean that Haskell uses a fundamentally different implementation technique.

> Type classes could just as well be implemented by expanding all invocations of the function with different instances and generating monomorphic code for every combination of instances.

As long as you don't use higher-ranked types.