NOTE: this library has been archived and is superceded by the Plato language
Platonic C# is a set of style and coding guidelines for cross-platform C# that encourage the usage of functional programming, referential transparency, and immutable data structures.
Image by Johnson Cameraface licensed usage under CC BY-NC-SA 2.0
The purpose of these rules are to:
- Make it easier for tools to analyze, transform, translate, and optimize C# code
- Make it simpler and faster to develop high quality software
Platonic C# code can be converted automatically into a pure functional language called Plato which in turn has an optimizer and can be easily compiled or translated to different targets (including JavaScript, and back to C#).
The key idea of Platonic C# is to restrict mutable data types so that they have at most one reference at any time. This idea is known as a unique type which is a restricted form of linear type.
This allows functions to retain referential transparency even when using mutable types.
- Only a subset of C# 7.3 features are supported
- No unsafe code is allowed
- A limited subset of external libraries are supported
- Structs are not supported (use classes instead)
- Classes many declare only properties and methods
- No abstract types
- No delegates
- Data types are immutable or mutable marked by the [Immutable] and [Mutable] attribute respectively.
- Immutable classes and both mutable and immutable interfaces, do not have settable properties
- Only mutable classes may have settable properties
- Static types must be immutable
- Immutable classes can only implement immutable interfaces and derive from immutable classes
- Immutable classes may not have a mutable class as a property
- Only classes may have properties with setters
- All property setters must be private.
- Classes with property setters
- No abstract members
- No events
- Methods are either
[Pure]
- meaning it has no side effects[ImpureWrite]
- writes to one of the fields[ImpureEffect]
- uses a mutable type
- Only
[Mutable]
types may have[ImpureWrite]
functions - Both
[Mutable]
and[Immutable]
types may have[ImpureEffect]
functions - No
async
methods
- No generator methods (e.g.,
yield return
andyield break
statements) - No goto statements
- No nested types
Platonic C# came from the idea of embedding a new language in C# that was pure functional and cross-platform. Pure functional languages offer opportunities for tools to rewrite and optimize code that cannot be safely applied to a language with side effects.
The challenge with embedding in C# directly was the requirement for a lot of boilerplate that does not make sense in a pure functional language with an advanced compiler.
Eventually this idea gave rise to a separate language called Plato that uses a subset of C# syntax, but has pure-functional semantics.
The Plato tool-chain and core libraries are being written in C# following the Platonic C# guidelines.
I have been using functional programming in C# for several years now, largely in the domain of real-time 3D geometry processing. The idea of Platonic C# has evolved from a set of coding guidelines that I follow, and have enforced with development teams that I lead.
Even though C# has released a rich set of syntactic constructs over recent years for writing code in a functional style, performance of functional programming patterns remains very poor due to how the C# and .NET compilers process and handles lambdas. This is less a short-coming of the compiler and more of an issue with the language design, which allows unconstrained side-effects and reflection. These provide a barrier to a whole family of interesting rewriting optimizations.
The other challenge with C# is that there is a split in terms of what language features can be used where. Many popular plug-in APIs (including Unity and Visual Studio) require using older versions of the language which have fewer features.
- A Roslyn code analyzer that enforces the Platonic code style
- An optimizer that converts Platonic C# into efficient byte code
- A Platonic C# => Plato translator S