Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Definitive guide on when to use Haskell typeclasses? [closed]

So, I understand algebraic types and type classes very well, but I'm interested in the software-engineering/best practices side of it.

What is the modern consensus, if any, on typeclasses? Are they evil? Are they handy? Should they be used, and when?

Here's my case-study. I'm writing an RTS-style game, and I have different kinds of "units" (tank, scout, etc.). Say I want to get the max health of each unit. My two thoughts on how to define their types are as follows:

Different constructors of an ADT:

data Unit = Scout ... | Tank ...

maxHealth :: Unit -> Int

maxHealth Scout  = 10

maxHealth Tank = 20

Typeclass for Unit, each kind is an instance

class Unit a where
    maxHealth :: a -> Int

instance Unit Scout where
    maxHealth scout = 10

instance Unit Tank where
    maxHealth tank = 20

Obviously, there is going to be many more fields and functions in the final product. (For example, each unit will have a different position, etc. so not all of the functions will be constant).

The trick is, there might be some functions that make sense for some units, but not others. For example, every unit will have a getPosition function, but a tank might have a getArmour function, which doesn't make sense for a scout without armour.

Which is the "generally accepted" way to write this if I want other Haskellers to be able to understand and follow my code?

like image 391
jmite Avatar asked Jul 25 '13 04:07

jmite


People also ask

What are Typeclasses used for?

Type classes are a powerful tool used in functional programming to enable ad-hoc polymorphism, more commonly known as overloading.

What is a type family Haskell?

Type families are parametric types that can be assigned specialized representations based on the type parameters they are instantiated with. They are the data type analogue of type classes: families are used to define overloaded data in the same way that classes are used to define overloaded functions.

What are type classes in Haskell What purpose do they serve?

In Haskell, type classes provide a structured way to control ad hoc polymorphism, or overloading. [For the stylistic reason we discussed in Section 3.1, we have chosen to define elem in infix form. == and || are the infix operators for equality and logical or, respectively.]

Is Haskell an OOP?

Haskell isn't an object-oriented language. All of the functionality built here from scratch already exists in a much more powerful form, using Haskell's type system.


1 Answers

Most Haskell programmers frown on needless typeclasses. These hurt type inference; you can't even make a list of Units without tricks; in GHC, there's all the secret dictionary passing; they somehow make the Haddocks harder to read; they can lead to brittle hierarchies ... maybe others can give you further reasons. I guess a good rule would be to use them when it's much more painful to avoid them. For instance, without Eq, you'd have to manually pass around the functions to compare, say, two [[[Int]]]s (or use some ad-hoc runtime tests), which is one of the pain points of ML programming.

Take a look at this blog post. Your first method of using a sum type is OK, but if you want to allow users to mod the game with new units or whatever, I'd suggest something like

data Unit = Unit { name :: String, maxHealth :: Int }

scout, tank :: Unit
scout = Unit { name = "scout", maxHealth = 10 }
tank  = Unit { name = "tank",  maxHealth = 20 }

allUnits = [ scout
           , tank
           , Unit { name = "another unit", maxHealth = 5 }
           ]

In your example, you need to encode somewhere that a tank has armor but a scout doesn't. The obvious possibility is to augment the Unit type with extra information like a Maybe Armor field or a list of special powers ... there's not necessarily a definitive way.

One heavyweight solution, probably overkill, is to use a library like Vinyl that provides extensible records, giving you a form of subtyping.

like image 200
Fixnum Avatar answered Sep 29 '22 11:09

Fixnum