Tutorial, Webinar
Exploring the Hidden Secrets within OCaml’s Local Function Types | OCaml Unboxed
Core Mechanics of Local Function Types
- Functions annotated with
localarguments exhibit hiddenlocalannotations in their partial applications. - If a function takes a
localargument, any intermediate closure created during partial application is also inferred aslocal. - This inference prevents "heap-to-stack" pointers by ensuring that a closure holding a local value cannot persist on the heap if the local value was intended for the stack.
Case Study: append_ints with Local Lists
- Example Setup: A recursive function
append_intstakes twoint listarguments, where the first argument is explicitly typed aslocal. - Safety Constraint: The function succeeds only because
intvalues are considered "global" and can be safely consed onto a global list, even if the source list was local. - Polymorphic Failure: Converting the function to polymorphic types causes a type error ("value escapes its region") because a generic local value cannot be safely stored in a global list structure.
- Result Type: The return type of the original definition appears global, but the intermediate partial application is secretly local.
Partial Application and Region Escapes
- Error Trigger: Attempting to partially apply
append_intsto a list (e.g.,map (append_ints [1; 2; 3])) results in a compilation error because the resulting closure attempts to capture a local list on the heap. - Implicit Hidden Local: Adding parentheses to the type signature (e.g.,
local list -> (list -> list)) does not alter the code but explicitly reveals that the intermediate function is a global closure containing a local argument, which is disallowed. - Standard Library Limitations: The standard
List.mapfunction lackslocalannotations, forcing the compiler to treat partial applications involving local arguments as potentially unsafe. - Resolution via Full Application: Fully applying the function before passing it to
mapresolves the error, as the local value is consumed immediately and does not need to be stored in a closure.
Workarounds and Syntax Considerations
atExpansion: Explicitly writingatexpansions in the type system can force the compiler to allocate the intermediate list on the heap, converting it to a global type that can be safely sub-modified to local.- Improved Error Messages: Jane Street updated the error message to explicitly warn that a "function or one of its parameters escape their region when partially applied," advising users to fully apply the function.
- Proposed Syntax Changes: The speaker suggests potential new syntax for function arrows that prohibit partial application to avoid these confusing "hidden local" semantics.
- Currying Anomalies: Standard functional programming assumptions that
A -> B -> Cis equivalent toA -> (B -> C)do not hold true forlocaltypes; the former allows full application without issues, while the latter introduces a hidden local closure.
Upcoming Development and Context
- Series Continuation: This content is part of a broader series on the local mode in Jane Street's OCaml compiler branch.
- Future Directions: There is ongoing consideration of syntax modifications to function definitions to prevent accidental creation of hidden locals during partial application.
- Compiler Behavior: The compiler infers the hidden
localstatus on partial applications automatically, even when the user does not explicitly type it.