Methods in Haskell

Haskell supports defining methods on custom data types using type classes. Here’s an example of how we can implement a similar structure to the Go code:

module Main where

import Text.Printf (printf)

data Rect = Rect { width :: Int, height :: Int }

class Shape a where
    area :: a -> Int
    perim :: a -> Int

instance Shape Rect where
    area r = width r * height r
    perim r = 2 * width r + 2 * height r

main :: IO ()
main = do
    let r = Rect { width = 10, height = 5 }
    
    -- Here we call the 2 methods defined for our data type
    printf "area: %d\n" (area r)
    printf "perim: %d\n" (perim r)

    -- In Haskell, we don't need to worry about pointers vs values
    -- The same functions work for both cases
    let rp = r
    printf "area: %d\n" (area rp)
    printf "perim: %d\n" (perim rp)

In this Haskell version:

  1. We define a Rect data type similar to the struct in the original code.

  2. We create a Shape type class that defines the area and perim methods.

  3. We make Rect an instance of Shape by implementing these methods.

  4. In the main function, we create a Rect and call the methods on it.

  5. Haskell doesn’t have the concept of pointers in the same way as Go. The same functions work for both cases, so we don’t need to demonstrate pointer receiver behavior explicitly.

To run this program, save it as shapes.hs and use:

$ runhaskell shapes.hs
area: 50
perim: 30
area: 50
perim: 30

Haskell uses type classes to achieve a similar effect to methods in object-oriented languages. This allows for polymorphic behavior while maintaining Haskell’s functional paradigm.

Next, we’ll look at Haskell’s mechanism for grouping and naming related sets of methods: type classes and their instances.