Interfaces in Elm

In Elm, we don’t have the concept of interfaces as in Go. Instead, we use type aliases and custom types to define common structures. We’ll implement a similar concept using custom types and type aliases.

First, let’s define our basic structure for geometric shapes:

type alias Geometry =
    { area : Float
    , perimeter : Float
    }

type Shape
    = Rectangle Float Float
    | Circle Float

Now, let’s implement functions to calculate area and perimeter for each shape:

calculateRectangle : Float -> Float -> Geometry
calculateRectangle width height =
    { area = width * height
    , perimeter = 2 * (width + height)
    }

calculateCircle : Float -> Geometry
calculateCircle radius =
    { area = pi * radius * radius
    , perimeter = 2 * pi * radius
    }

We can create a function to measure any shape:

measure : Shape -> Geometry
measure shape =
    case shape of
        Rectangle width height ->
            calculateRectangle width height
        
        Circle radius ->
            calculateCircle radius

Now, let’s put it all together in a main function:

import Html exposing (Html, div, text)

main : Html msg
main =
    let
        rect = Rectangle 3 4
        circle = Circle 5
        
        measureAndFormat : Shape -> String
        measureAndFormat shape =
            let
                geometry = measure shape
            in
            String.join "\n"
                [ Debug.toString shape
                , "Area: " ++ String.fromFloat geometry.area
                , "Perimeter: " ++ String.fromFloat geometry.perimeter
                , ""
                ]
    in
    div []
        [ text (measureAndFormat rect)
        , text (measureAndFormat circle)
        ]

To run this Elm program, you would typically compile it to JavaScript and run it in a web browser. Here’s what the output might look like:

Rectangle 3 4
Area: 12
Perimeter: 14

Circle 5
Area: 78.53981633974483
Perimeter: 31.41592653589793

In this Elm version, we’ve implemented a similar concept to Go’s interfaces using custom types and type aliases. The Shape type represents different geometric shapes, and the Geometry type alias defines the structure for area and perimeter calculations. The measure function acts similarly to the measure function in the Go example, working with any Shape.

Elm’s type system and pattern matching allow us to achieve a similar level of polymorphism as Go’s interfaces, but in a more functional programming style.