As I understand the Type Class is that it's not something concrete but just a construct for ad-hoc and parametric polymorphism. Eq and Semigroup are examples of type classes. On the other hand, there is Algebraic data type, which is a concrete composite type, for example, Either and Maybe. And they are also Functors.
So, there is a specification for Algebraic data types for JavaScript: https://github.com/fantasyland/fantasy-land. On this page, Setoid(Eq), Ord and Semigroup are also ADT. But is it correct? If so, they are composite of what types?
I also find out this article regarding type classes, and here Functors and Monads are type classes. https://typelevel.org/cats/typeclasses.html#type-classes-in-cats. And, is it means that Either and Maybe are type classes as well?
Is Eq a type class or algebraic data type? Or both? Same for Functor
We collect data (values, terms) into types (data types). We can collect types into type classes.
1
, "a"
, true
, Some(1)
, None
, ... are values. They belong to types, Int
, String
, Boolean
, Option[Int]
, ... Types can belong to type classes, Eq
, Ord
, Functor
, ...
ADT (algebraic data type) is a data type constructed via sum and product
// Scala
sealed trait MyTrait
case class MyClass1(i: Int, s: String) extends MyTrait
case class MyClass2(b: Boolean) extends MyTrait
-- Haskell
data MyTrait = MyClass1 { i :: Int, s :: String } | MyClass2 { b :: Bool }
Here MyTrait
is a sum of MyClass1
and MyClass2
. MyClass1
is a product of Int
and String
. MyClass2
is a product of single multiplier Boolean
.
There are also data types that are not ADT. E.g. function types A => B
, union types , intersection types A | B
A & B
or A with B
, existential types, etc. Scala ADT are automatically generalized ADT (GADT) in Haskell terminology. There are generalizations of ADT in dependently typed languages, Sigma- and Pi-types (i.e. dependent sum and product).
Type classes is FP way to describe a behavior (via ad hoc polymorphism, early binding, static/compile-time dispatch). We can make a type an instance of a type class
// type class
trait MyTypeclass[A] {
def foo(a: A): Unit
}
object MyTypeclass {
// instances
implicit val myTraitMyTypeclass: MyTypeclass[MyTrait] = new MyTypeclass[MyTrait] {
override def foo(a: MyTrait): Unit = a match {
case MyClass1(i, s) => println(s"MyTrait: MyClass1: i=$i, s=$s")
case MyClass2(b) => println(s"MyTrait: MyClass2: b=$b")
}
}
implicit val myClass1MyTypeclass: MyTypeclass[MyClass1] = new MyTypeclass[MyClass1] {
override def foo(a: MyClass1): Unit = println(s"MyClass1: i=${a.i}, s=${a.s}")
}
implicit val myClass2MyTypeclass: MyTypeclass[MyClass2] = new MyTypeclass[MyClass2] {
override def foo(a: MyClass2): Unit = println(s"MyClass2: b=${a.b}")
}
}
class MyTypeclass a where
foo :: a -> IO ()
instance MyTypeclass MyTrait where
foo (MyClass1 i s) = print ("MyClass1: i=" ++ show i ++ ", s=" ++ show s)
foo (MyClass2 b) = print ("MyClass2: b=" ++ show b)
Here MyClass1
, MyClass2
, MyTrait
(in Haskell only MyTrait
) are types, they are instances of the type class MyTypeclass
.
An alternative to typeclasses (another way to describe a behavior) is OOP inheritance (via subtyping polymorphism, late binding, dynamic/runtime dispatch)
sealed trait MyTrait {
def foo(): Unit
}
case class MyClass1(i: Int, s: String) extends MyTrait {
override def foo(): Unit = println(s"MyClass1: i=$i, s=$s")
}
case class MyClass2(b: Boolean) extends MyTrait {
override def foo(): Unit = println(s"MyClass2: b=$b")
}
We can lift an ADT into a type class. For example standard ADT
sealed trait Option[+A]
case class Some[+A](a: A) extends Option[A]
case object None extends Option[Nothing]
data Maybe a = Just a | Nothing
can become a type class and its instances
trait Option[A]
case class Some[A](a: A)
case object None
type None = None.type
implicit def someOption[A]: Option[Some[A]] = new Option[Some[A]] {}
implicit val noneOption: Option[None] = new Option[None] {}
class Maybe a
newtype Just a = Just a
data Nothing a = Nothing
instance Maybe (Just a)
instance Maybe (Nothing a)
On this page,
Setoid
(Eq
),Ord
andSemigroup
are also ADT. But is it correct? If so, they are composite of what types?
Normally, Eq
, Ord
, Semigroup
are not ADT. They are not constructed via sum and product. They are type classes. They describe behavior, namely how to compare elements for equality, how to compare them for order, how to add elements, what is unit element. They "consists" of all types declared as their instances, e.g. Int
, String
etc. (i.e. where the corresponding behavior is implemented in some specific way).
is it means that
Either
andMaybe
are type classes as well?
Normally, Either
and Maybe
are not type classes, they are ADT. But if we really want we can lift ADT into a type class as I showed above.
Is
Eq
a type class or algebraic data type? Or both? Same forFunctor
.
Eq
and Functor
are type classes, not ADT.