Content
Content copied to clipboard
ACCU 2021: type class best practice
I watched your ACCU 2021 talk on YouTube and found the syntax comparisons interesting. You mentioned best practice at a certain point (I think it was in reference to C++20 parametric polymorphism syntax), so I thought I'd point out something about best practice regarding the use of Haskell type classes, which you may already be aware of. In particular, it's typically recommended that you only use type classes when the functions satisfy laws that express useful generic behaviour for all instances of the type class (see this and this). I know your Shape
example was just intended to demonstrate type class syntax, but there are better solutions to the shape problem, and more idiomatic examples of type classes.
One of the following monomorphic solutions might be preferable if you need to create collections that contain both rectangles and circles, or if you need to write a Shape
-valued function that can return a rectangle or a circle, depending on the input, e.g. a Shape
parser:
data Shape = Circle Float | Rectangle Float Float
name :: Shape -> String
name (Circle _) = "Circle"
name (Rectangle _ _) = "Rectangle"
area :: Shape -> Float
area (Circle r) = pi*r*r
area (Rectangle w h) = w*h
perimeter :: Shape -> Float
perimeter (Circle r) = 2*pi*r
perimeter (Rectangle w h) = 2*(w+h)
-- ========== OR ==========
data Shape=Shape {name::String, area::Float, perimeter::Float}
circle :: Float -> Shape
circle r = Shape {name="Circle", area=pi*r*r, perimeter=2*pi*r}
rectangle :: Float -> Float -> Shape
rectangle w h = Shape {name="Rectangle", area=w*h, perimeter=2*(w+h)}
A more idiomatic example of the use of type classes would be to show how you could (manually) define an Eq
instance for Shape
, and to briefly explain how that instance satisfies the five expected properties.