Skip to content

Instantly share code, notes, and snippets.

@BebeSparkelSparkel
Created February 16, 2025 15:49
Show Gist options
  • Select an option

  • Save BebeSparkelSparkel/24e6232b19b94f6c93e4812a8b48fb9b to your computer and use it in GitHub Desktop.

Select an option

Save BebeSparkelSparkel/24e6232b19b94f6c93e4812a8b48fb9b to your computer and use it in GitHub Desktop.

Are Modules Just Functions?

A deep dive into programming language design and abstraction mechanisms

OCaml's sophisticated module system is often touted as one of its standout features, especially when compared to Haskell's more limited facilities. But as we dig deeper into modern programming language design, an intriguing question emerges: are modules fundamentally different from functions, or are they just a specialized syntax for something we could achieve with first-class functions and a richer type system?

Let's explore this by building up from first principles.

The Traditional View

Traditionally, modules and functions have been seen as distinct concepts:

  • Modules are static, compile-time constructs for organizing code
  • Functions are dynamic, runtime constructs for computation
  • Modules can contain types and type classes
  • Functions work with values

But this distinction starts to blur when we consider that functions can return multiple values, create local scopes, and (in some languages) work with types as parameters.

Breaking Down the Barriers

With a sufficiently powerful type system, many module features can be replicated using functions:

  1. Type Abstraction: Using type variables and type classes/traits
  2. Information Hiding: Through existential types and local scopes
  3. Interface Definition: Via type classes or trait bounds
  4. Composition: Through function composition

For example, what looks like this in OCaml:

module type Set = sig
  type t
  type elt
  val empty : t
  val add : elt -> t -> t
end

Could conceptually be expressed as a function returning an existential type:

makeSet :: exists s. (
    s,                  -- empty
    a -> s -> s,        -- add
    a -> s -> Bool      -- member
)

The Missing Pieces

However, current functional languages like Haskell lack some key features that would make this equivalence more practical:

  1. Local Type Declarations: The ability to define types within function scope
  2. Local Type Classes: Declaring interfaces locally
  3. Local Instances: Implementing interfaces for local types
  4. Clean Name Management: Better syntax for exporting multiple named values

With these features, functions could serve as a more general abstraction mechanism that subsumes many module system features.

Performance Considerations

While one might think that function-based modules would incur runtime overhead, modern optimizers can often eliminate this through:

  • Inlining
  • Specialization
  • Partial evaluation

This means the distinction between "static" modules and "dynamic" functions often disappears in the compiled code.

A Unified Future?

This suggests an interesting direction for programming language design: unifying modules and functions into a single, more general abstraction mechanism. Imagine syntax like:

makeSet = scope {
    data Set a = Set [a]
    
    empty = Set []
    add x (Set xs) = Set (x:xs)
    member x (Set xs) = x `elem` xs
}

This would combine the ergonomics of modules with the flexibility of functions.

Conclusion

While current module systems offer important practical benefits, particularly around separate compilation and code organization, their core abstraction capabilities could potentially be expressed through a sufficiently enhanced function system. This suggests that the traditional distinction between modules and functions might be more about historical accident and implementation constraints than fundamental computer science.

The future might lie in unifying these concepts, giving us the best of both worlds: the static guarantees and organizational benefits of modules with the flexibility and composability of functions.

What do you think? Are modules truly distinct from functions, or are they just a specialized syntax for a particular kind of functional abstraction? Let me know your thoughts below!

#ProgrammingLanguages #TypeTheory #FunctionalProgramming

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment