4 ms·
From an abstract PL theory POV, Haskell's key innovation over ML was HKTs. It was an experiment at the time, but one that was successful beyond all expectation:
by YorkshireSeason 9y ago
From an abstract PL theory POV, Haskell's key innovation over ML was HKTs.
It was an experiment at the time, but one that was successful beyond
all expectation: I cannot imagine designing a new PL without HKTs. (Note
that Rust is also trying to add HKTs, but has been running into difficulties with type-based lifetime tracking IIRC.)
Implicits are a generalisation of default arguments (I don't know
where they were pioneered, maybe C++). Implicits were first tried in
Haskell [1]. Scala refined them in several steps, the last being [2]
which represents implicits on the type leve. Mimicking type classes via implicits
is a well-established Scala idiom [3].
[1] J. R. Lewis, J. Launchbury, E. Meijer, M. B. Shields, Implicit
Parameters: Dynamic Scoping with Static Types. https://galois.com/wp-content/uploads/2014/08/pub_JL_ImplicitParameters.pdf https://galois.com/wp-content/uploads/2014/08/pub_JL_Implici...
[2] M. Odersky, A. Biboudis, F. Liu, O. Blanvillain,
Simplicitly: Foundations and Applications of Implicit Function Types.
https://infoscience.epfl.ch/record/229878/files/simplicitly_1.pdf https://infoscience.epfl.ch/record/229878/files/simplicitly_...
[3] B. C. d. S. Oliveira, A. Moors, M. Odersky, Type Classes as
Objects and Implicits. http://ropas.snu.ac.kr/~bruno/papers/TypeClasses.pdf http://ropas.snu.ac.kr/~bruno/papers/TypeClasses.pdf
- saosebastiao 9y ago> Implicits are a generalisation of default arguments. There is an extreme semantic difference between an implicit parameter and a default argument. Have you spent any time at all using them? That's like claiming HKT is just a generalization of type constructors. Would you claim that HKT isn't anything new or novel because constructors have been around forever?
- YorkshireSeason 9y ago> Have you spent any time at all using them? Sure I have used both. Default arguments and implicits both have the same key idea: you can omit arguments to functions, and the compiler, guided by type information, synthesises the missing arguments during compilation. In order to understand the difference between both, it is crucial to realise that this compile-time synthesis of missing arguments has two related but different dimensions. - Declaration that an argument is allowed to be omitted (and hence synthesised automatically). - Declaration of the missing argument that is used in this synthesis. Default arguments merge these two into one, e.g. with def f ( int x ) ( bool b = false ) = ... f (2) f (2) all calls f(2) become f(2)(false). The problem with this is that the devault value to be used in synthesis cannot be context dependent. Implicit arguments separate these two, enabling the programmer to make default context dependent, e. g. def f ( int x ) ( implicit bool b ) = ... implicit val c = true f (2) implicit val c = false f (2) Now the first call f(2) is rewritten to f(2)(true), while the second becomes f(2)(false). > Would you claim that HKT isn't anything new or novel because constructors have been around forever? I'm not sure I see the connection: constructors are program constructs, while HKTs are "types for types".
- ionforce 9y agoMaybe a disagreement here is fueled by the power level difference in these two features. Beyond the superficial injection examples, Scala implicits also support injecting values constructed dynamically and also recursive/derived implicits.
- YorkshireSeason 9y ago> injecting values constructed dynamically You can also do this with default arguments, e.g. like so: let f x y = let g (a = x+1) b = ... ... For example the following is valid OCaml: let bump ?(step = 1) x = let waa ?( a = step+17 ) b = a * b in x + step + waa 666;; Here the function waa has a default argument whose default argument depends on bump's default argument. > recursive/derived implicits Recursion is quite restricted, for example this is not valid Scala: def f ( x : Int ) ( implicit y : Int ) : Int = { implicit val a = 17 f ( x+1 ) }
- lptk 9y agoYour example of nested functions with default arguments does not correspond to what derived implicits do. As a result of implicit resolution, an expression with an arbitrary number of subexpressions may be synthesized, the shape of which depends on the types involves. Default parameters simply cannot do that. The example you give to justify "recursion is quite restricted" is not a restriction on recursion at all, it's an ambiguity problem. Define `a` as `y` to shadow the function parameter, and it compiles.
- YorkshireSeason 9y ago> does not correspond to what derived implicits do I did not claim it did. The first example disproved ionforce's claim that default values cannot be constructed dynamically. > Define `a` as `y` to shadow the function parameter, Whoops, yes that's correct. I didn't realise this was possible.
- 9y ago
- naasking 9y agoThanks for the Simplicity reference, hadn't seen that yet. Seems like it builds on the implicit calculus [1], which applies more generally to any lambda calculus than in the Scala context. [1] http://homepages.inf.ed.ac.uk/wadler/papers/implicits/implicits.pdf http://homepages.inf.ed.ac.uk/wadler/papers/implicits/implic...
- lptk 9y ago> Haskell's key innovation over ML was HKTs In fact, ML modules have had higher-kinded types [1] since before Haskell even existed. I guess Haskell's main innovation in this domain is really its very convenient higher-kinded parametric polymorphism with type classes. [1] MacQueen, D B (1984). Modules for Standard ML. Conference Record of the 1984 ACM Symposium on LISP and Functional Programming Languages. 198-207.
- YorkshireSeason 9y agoThanks. That's really interesting. I need to read MacQueen's paper. Is this full HKT, in the sense that all constructions wiht HKTs can be encoded in MacQueen's system?
- lptk 8y agoIf by "all constructions wiht HKTs", you mean what can be done with HKTs in Haskell, then I'd say yes. It is well-known that ML modules provide a very advanced level of expressiveness, especially since OCaml's introduction of first-class modules. Also, Scala took this idea further and provides principled recursive first-class modules (which Scala calls dependent object types). The problem is that modules in ML have a verbose syntax and are clunky to use compared to type classes. OCaml's modular implicits aim to make this better (see https://arxiv.org/abs/1512.01895 https://arxiv.org/abs/1512.01895), taking inspiration from Sala's implicits.
- YorkshireSeason 8y agoI understand that making modules first-class gives them a lot of expressivity. But they are a fairly recent development" at least in OCaml the come much after Haskell. But are modules in MacQueen's sense first-class?