Arun Pandian M

Arun Pandian M

Android Dev | Full-Stack & AI Learner

Product Types: Why Types Behave Like Multiplication

There’s a point in programming where types stop feeling like simple containers and start behaving like algebra.

https://storage.googleapis.com/lambdabricks-cd393.firebasestorage.app/fp_product_type.svg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=firebase-adminsdk-fbsvc%40lambdabricks-cd393.iam.gserviceaccount.com%2F20260523%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20260523T135228Z&X-Goog-Expires=3600&X-Goog-SignedHeaders=host&X-Goog-Signature=0a75fddadf074feaa67ab42121465e6d5aed118d4b18420ad2d06ac20656062a0e456de5f06c7bd582fec246f0e4c64a20a9ca474b70ca71866b18cd26db6ba3e1c39aaf314a1cb48ee19bc076859ddbe198a09594de7863ffc0ffc6c025e6e08aaf91ba6cadc0a64e560f56a1f1787672a04da5028132c0467494e4e2911ab5194ad264f683a6ad32fffc07faaf1f5fd391c73e75feaefe48587cff4c6d1907d10a8c7fba6b8c5e436f4712ade982c49b5203abf5b80c69d5292a1a57208216d6cb5a0db477594a352e0324796c76c7d3f41b00d79e16b44acae2f8166d16c4201a19f035b9303d63889a6e34eb529c6f1abe283a75d698ffaf86ba61a4550d

At first, a pair or a data class looks ordinary:

data class User(
    val name: String,
    val age: Int
)

But underneath, something deeper is happening.

This User type is not just a structure holding values. It is actually a product type — one of the foundational building blocks of Algebraic Data Types (ADTs), Functional Programming, and Category Theory.

Once you see this, you start noticing algebra everywhere in programming.

What Is a Product Type?

A product type is a type that combines multiple values together into a single structure.

In Kotlin:

data class User(
    val name: String,
    val age: Int
)

contains:

  • a String
  • a Int
  • together.

    You can think of it mathematically as:

    String × Int

    The × is important.

    Product types are called “products” because the number of possible values multiplies.

    Why “Product”?

    Suppose:

    Bool = { true, false }

    and:

    Color = { red, green, blue }

    Then:

    Pair<Boolean, Color>

    can contain:

    (true, red)
    (true, green)
    (true, blue)
    (false, red)
    (false, green)
    (false, blue)

    There are:

    2 × 3 = 6. possible combinations. That multiplication behavior is why these are called product types.

    The Canonical Product Type: Pair

    Most programming languages implement product types using:

  • Pair
  • Tuple
  • Struct
  • Record
  • Data class
  • In Kotlin:

    val user =
        Pair("Arun", 28)

    or:

    val user =
        "Arun" to 28

    This is simply:

    String × Int

    Product Types Combine Information

    A product type means:

    ALL values exist together.

    For example:

    data class Address(
        val city: String,
        val zipCode: String
    )

    An Address always contains:

  • city
  • zipCode
  • simultaneously.

    This is very different from sum types like sealed class, where only one possibility exists at a time.

    Product Types Are Not Strictly Commutative

    Consider these two types:

    Pair<Int, Boolean>

    and:

    Pair<Boolean, Int>

    They are different types. You cannot pass one where the other is expected. The compiler treats them differently because the order matters. But something interesting is happening underneath.

    Same Information, Different Arrangement

    Even though:

    Pair<Int, Boolean>

    and:

    Pair<Boolean, Int>

    are structurally different, they still carry the same information:

  • one Int
  • one Boolean
  • This is similar to:

  • big endian
  • little endian
  • The arrangement changes. The information does not.

    Commutativity Up To Isomorphism

    There exists a reversible transformation between them.

    fun <A, B> swap(
        pair: Pair<A, B>
    ): Pair<B, A> {
    
        return Pair(
            pair.second,
            pair.first
        )
    }

    Nothing is lost. We can always reverse the operation.

    That means the two structures are: isomorphic

    Mathematically:

    (A, B) ≅ (B, A)

    This idea is called:

    commutativity up to isomorphism

    The structures are not strictly equal, but they are structurally equivalent.

    Nested Product Types

    We can combine more than two values.

    One way is nesting pairs:

    ((A, B), C)

    or:

    (A, (B, C))

    These look different. But again, they contain the same information.

    Both contain:

  • A
  • B
  • C
  • The grouping changes. The information does not.

    Associativity Up To Isomorphism

    We can transform between the two structures:

    fun <A, B, C> reassociate(
        value: Pair<Pair<A, B>, C>
    ): Pair<A, Pair<B, C>> {
    
        return Pair(
            value.first.first,
            Pair(
                value.first.second,
                value.second
            )
        )
    }

    Again:

  • no information is lost
  • reversible transformation exists
  • So:

    ((A,B),C)
    ≅
    (A,(B,C))

    This mirrors arithmetic associativity:

    (a × b) × c
    =
    a × (b × c)

    except here the equality is: up to isomorphism

    not strict equality.

    Representation vs Information

    This is one of the deepest ideas in category theory.Different structures may represent the same information.

    Category theory often cares more about:

    structure preservation

    than exact representation.

    If two structures can be transformed back and forth without losing information, they are often treated as “essentially the same.”

    Unit Type as Identity

    Now things get even more algebraic.

    In arithmetic:

    a × 1 = a

    because multiplying by 1 changes nothing. Product types have something similar. The Unit type behaves like 1.

    In Kotlin: Unit has exactly one possible value.

    So:

    Pair<String, Unit>

    does not really contain more information than: String

    The Unit contributes nothing meaningful.

    Isomorphism With Unit

    We can remove Unit:

    fun <A> rho(
        pair: Pair<A, Unit>
    ): A = pair.first

    and add it back:

    fun <A> rhoInv(
        value: A
    ): Pair<A, Unit> =
        Pair(value, Unit)

    So:

    (A, Unit) ≅ A

    Again:

  • representation changes
  • information stays same
  • Types Start Behaving Like Algebra

    At this point, product types begin looking very mathematical.

    AlgebraTypes
    multiplicationproduct types
    associativitytuple regrouping
    identity elementUnit
    commutativityswap isomorphism

    This is why they are called:

    Algebraic Data Types

    Types behave algebraically.

    Product Types in Kotlin

    Kotlin uses product types everywhere.

    Data Classes

    data class User(
        val name: String,
        val age: Int
    )

    UI State

    data class UiState(
        val loading: Boolean,
        val users: List<User>,
        val error: String?
    )

    API Models

    data class ApiResponse(
        val code: Int,
        val message: String
    )

    Domain Modeling

    data class Money(
        val amount: Double,
        val currency: String
    )

    All of these are product types. They combine independent pieces of information into one structure.

    Why Named Product Types Matter

    Tuples become difficult to understand as systems grow.

    This is bad:

    Pair<String, Boolean>

    What does the Boolean mean?

    Instead, named product types communicate meaning:

    data class Statement(
        val text: String,
        val valid: Boolean
    )

    Now the structure carries semantic meaning.

    This improves:

  • readability
  • maintainability
  • domain modeling
  • type safety
  • Type Constructor vs Data Constructor

    In Haskell:

    data Pair a b = P a b

    two different ideas exist.

    Type Constructor

    Pair

    creates TYPES.

    Example:

    Pair String Bool

    Data Constructor

    P 

    creates VALUES.

    Example:

    In Haskell:

    P "Hello" True

    Kotlin hides this distinction because classes act as both.

    Product Types as ADT Foundations

    Product types are one half of Algebraic Data Types.

    ADTs are built from:

  • product types
  • sum types
  • Together, they form the foundation of functional programming data modeling.

    Final Thoughts

    Product types may look simple at first.

    But underneath, they reveal something profound:

    types preserve structure algebraically

    Pairs, tuples, data classes, records, and structs are not just containers. They are mathematical compositions of information.

    And once you begin seeing product types as algebra instead of syntax, a large part of functional programming and category theory starts making much more sense.

    #TypeTheory#AlgebraicDataTypes#ComposableSystems#SoftwareDesign#FPConcepts#TypeComposition#CategoryTheory#SumTypes#FunctionalProgramming#ADT#KotlinFP#MathForDevelopers#ProgrammingConcepts#ProductTypes#LearnInPublic