Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding when to uses type classes or GADT's?

I'm trying to figure out the differences between type classes and GADTS, especially when using -XMultiParamTypeClasses extension.

Both appear to have similar uses:

class MyClass a b where
  f :: a -> b -> Bool

instance MyClass String String where
  f s1 s2 = ...

instance MyClass Int Int where
  f i1 i2 = ...

data Gadt a where
  F :: String -> String -> Bool
  F2 :: Int -> Int -> Bool

So far, the only difference I really see is that GADT's enable a function type interface to have a flexible number arguments:

data Gadt a where
  PassTwoArgs :: String -> String -> Gadt Bool
  PassOneArgs :: String -> Gadt Bool

myFunction :: Gadt a -> a
myFunction (PassTwoArgs s1 s2) = ...
myFunction (PassOneArgs s1) = ...

Whilst this isn't easily done with type classes.

Are there any other differences or use cases to use one over the other?

like image 566
Babra Cunningham Avatar asked Feb 25 '17 13:02

Babra Cunningham


2 Answers

If you have a class, you can add new instances at any time.

If you use a GADT, you have a data structure which is fixed forever. You can never add new cases to it, without altering the original definition. However, as you note, it's far more flexible.

Really, they're intended for different use-cases. Classes are for when you want to be able to do a thing to lots of different data types which otherwise have nothing to do with each other. (E.g., you can do (==) on Int and on String, but those types aren't very similar.) GADTs are for when you want to have one type, but some of its type parameters tell you something about it. The canonical example is where the GADT represents an expression in some programming language, and you want to use the Haskell type system to enforce the other language's type system.

What classes are not like are the "classes" we use in object-oriented programming. ;-) Please put all such ideas out of your brain.

like image 61
MathematicalOrchid Avatar answered Sep 27 '22 20:09

MathematicalOrchid


If you need pattern matching, use a (G)ADT. If you need third parties to be able to implement your interface, use a typeclass.

My intuition is to use typeclasses as much as possible; if I absolutely need pattern matching, then I'll reach for a (G)ADT. I usually don't need it.

like image 36
Yawar Avatar answered Sep 27 '22 20:09

Yawar