Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Composite" algebraic data types in Scala and Haskell

While trying to describe a portion of Sql with Algebraic Data Types in Scala I met a neccessity to create subtraits of the root trait which represents the data type. Since meeting this requirement produced a code that I'm not sure is possible to represent with Haskell's ADTs, and since, in difference to Haskell, ADT is not a native construct to Scala, I am now wondering:

  1. Am I right that it is impossible to represent a model such as a type Sql having a "subtype" Statement having a constructor Select in Haskell? (It seems like this may be related).
  2. If so, is the term "ADT" applicable to the code that I produced?
  3. If it is, does this make Scala actually more powerful than Haskell in that aspect?
  4. If it doesn't, what are the reasons for this functionality not to be implemented in Haskell? It makes me think that I might be overcomplicating things in my model

Here's the model I'm talking about:

sealed trait Sql


sealed trait Statement 
  extends Sql

sealed case class Union 
  ( left : Statement, 
    right : Statement ) 
  extends Statement

sealed case class Select
  ( /** other fields don't matter **/
    where : Where )
  extends Statement


sealed trait Where 
  extends Sql

sealed case class And
  ( left : Where,
    right : Where )
  extends Where

sealed case class Or
  ( left : Where,
    right : Where )
  extends Where

sealed case class Equals
  ( /** fields don't matter **/ )
  extends Where
like image 893
Nikita Volkov Avatar asked Aug 21 '12 12:08

Nikita Volkov


People also ask

What is composite data type in Haskell?

A composite data type is constructed from other types. The most common composite data types in Haskell are lists and tuples.

What is algebraic data type in Scala?

What Are Algebraic Data Types? ADTs are commonly used in Scala. Simply put, an algebraic data type is any data that uses the Product or Sum pattern. The question now shifts to understanding what Product and Sum Types are.

How data types are combined in Haskell?

You can combine multiple types with an and (for example, a name is a String and another String ), or you can combine types with an or (for example, a Bool is a True data constructor or a False data constructor). Types that are made by combining other types with an and are called product types.

Why is it called algebraic data types?

Algebra of ADTs Product types and sum types are collectively called “algebraic” data types because they have algebraic properties similar to normal integers.


1 Answers

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 Monads in Scala, you have to write lots of code in the parts that use the Monads, 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.

like image 132
dflemstr Avatar answered Oct 28 '22 18:10

dflemstr