1. No, since your root trait is sealed, it is possible to represent the presented hierarchy as ADTs:
data Sql = Statement Statement | Where Where
-- ^ This is the *type* called `Statement`
-- ^ This is the *constructor* called `Statement`
data Statement = Union Statement Statement | Select Where
data Where = And Where Where | Or Where Where | Equals
It is possible in this case, because you are able to enumerate all of the "subclasses" of your data type (Sql
in this case), which makes it possible to convert them into ADT constructors. It is only difficult to emulate type hierarchies as ADTs if you want to allow "constructors"/"sub-classes" to be added arbitrarily by the user.
2. The term ADT is never applicable to Scala code since Scala lacks ADTs in the language. However, the classes that you've presented behave similarly to ADTs, so I'd say "close enough."
3 & 4. The languages have different strengths and weaknesses.
Haskell can emulate every Scala language feature, and Scala can emulate every Haskell feature, since both languages are turing complete, and allow for different levels of meta-programming. Haskell does of course have Template Haskell, which allows for anything to be emulated -- you could probably use TH to be able to write Scala code in a Haskell file and have it be compiled as Haskell.
Objects and inheritance are not needed in Haskell, and ADTs are mostly not needed in Scala, so there's no reason to compare the two. Most object-oriented features can also be emulated with simple Haskell type classes and data types, and using module boundaries. ADTs can be emulated in Scala with case classes, and Haskell type classes can be emulated with implicit parameters and implicit object instances.
However, I'd say that it in general is easier to emulate certain Scala features in Haskell, though, because Haskell allows for more "implicit language extensions" than Scala does. What I mean by that is that if you want to emulate Haskell Monad
s in Scala, you have to write lots of code in the parts that use the Monad
s, while if you want to emulate, let's say, Scala's delimited continuations or implicit parameters in Haskell, you can simply write a Monad
instance (for continuations) or a multi-param type class (for implicit parameters) once for that, and the code that you later write in your actual functions will look very close to the Scala code without much boiler plate. Many if not most of Scala's advanced features do also originate from either Haskell or OCaml, so they are already there and don't need to be translated.
In other words: The complex code required to add the new feature only has to be added in one location in Haskell, after which it can be used in multiple locations very easily, while you often have to add lots of "noise" everywhere in your Scala code if you want to emulate a Haskell feature.
data Maybe a = None | Just a
can be mimicked assealed trait Maybe[A]; case object None extends Maybe[A]; case class Just[A](a : A) extends Maybe[A]
– Nikita Volkov