No it is really not. Haskell only really has one category of any import, typically denoted 'Hask'. There is no builtin way to embed or express arbitrary categories in Haskell. It's not even clear what this would mean, given that Haskell only has one conception of arrow (the function type '->'). In fact, Haskell is so far removed from true category theory that we have to use a compiler plugin (CCC by Conal Elliot) to get anything approaching compilation to arbitrary categories.
Haskell is based on the polymorphically typed lambda calculus. Some decades after its design, some people realized they could use some abstract algebra concepts to help structure programs. You can use these concepts in any language with a sufficiently expressive type system. It is not specific to Haskell
The fact that many organizations working on massive datasets have embraced Scala proves there are not many alternatives around, sadly.
can you elaborate more on that?
Clojure was designed and marketed for the enterprise. Builds on the JVM, full Java interop, emphasis on pragmatism.
Haskell is category theory
as a language.
I disagree with this. Haskell's creation [1, 2] predates the realisation (by the FP community at large)
of the close connection between parts of category theory and parts of
pure functional programming, which happened in the 1990s, perhaps
driven by Moggi's realisation that monads are a fundamental
abstraction in computation that can reconcile effects with pure functional computation. More importantly, there is no category
"Hask" of Haskell programs, and there isn't even a candidate category that's even close.One of Odersky's motives in creating Scala was bringing the power of Haskell into the JVM world, although this is not the only motive (tight integration of OO and FP being another).
Haskell's key innovation over its predecessors (Miranda and ML) was the addition of higher-kinded types, which in turn made ad-hoc polymorphism digestable in a typed world (in the form of type-classes). The combination of HKTs and type-classes enables the monadic abstractions that contemporary Haskell programming is widely known for today.
Note that Scala has HKTs and type classes (via implicits), so Haskell programs can typically transliterated into idiomatic Scala without major complications.
[1] P. Hudak, J. Hughes, S. Peyton Jones, P. Wadler, A History of Haskell: Being Lazy With Class. http://haskell.cs.yale.edu/wp-content/uploads/2011/02/histor...
[2] Interview with Simon Peyton-Jones. http://www.cs.cmu.edu/~popl-interviews/peytonjones.html
[3] E. Moggi, Notions of Computation and Monads. https://core.ac.uk/download/pdf/21173011.pdf
My general assumption is that if Scala was intended to be category theory, implemented, something along the lines of scalaz or cats would have been built into the language -- the philosophy of the language does not include a JS-esque philosophy of small stdlib, big library ecosystem.
He mentions module systems fairly early on.
AFAIK, Odersky doesn't particularly like people trying to replicate Haskell patterns in Scala. For example, he thinks using monads for most effects is inappropriate.
> Odersky has long claimed ML as his primary functional programming influence, not Haskell.
I'm not sure why you would think that. Odersky has long claimed ML as his primary functional programming influence, not Haskell. It does have HKT, so there's that...but that's about it. Typeclasses aren't really a part of the language. They were made possible by implicits. They have since had some language level support (context bounds), but that is more of a nice to have than a primary influence.
Just because Scala can "do" Haskell doesn't mean odersky was inspired by it any more than ML or Java.
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_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_...
[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
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?
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".
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 ) }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.
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.
But I don't think that is what they meant. I think they meant something along the lines of what I said above:
> an expression with an arbitrary number of subexpressions may be synthesized, the shape of which depends on the types involves
Saying implicits are a generalization of default arguments because they're both synthesized during compilation is like saying steam trains are a generalization of pipes because they're both made of metal. It elides too big a difference to be helpful, to the point that it's actually misleading.
This isn't true though - that's not what implicits are for and not how they're used. Indeed the clearest proof is that Scala still has default arguments, and they still have the behaviour given in your OCaml example. They're different things.
I should not have said the key idea, but a key idea.
Default arguments are convenient if you don't need context dependence of elided arguments. I'd probably have remove defaults in order to have a smaller and more simple language.
[1] http://homepages.inf.ed.ac.uk/wadler/papers/implicits/implic...
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.
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), taking inspiration from Sala's implicits.