An effect system extends an ordinary type system so that the type of a function records not only what kind of value it returns but also what side effects it may perform along the way, such as reading or writing state, doing input and output, throwing exceptions, or never terminating. Effects that were previously invisible become part of the type signature, so the compiler can keep functional code honest about which parts are pure and which are not.
The Koka language is a clear example. Its documentation states that “Koka tracks the (side) effects of every function in its type, where pure and effectful computations are distinguished,” and describes this precise effect typing as giving the language a solid semantics that makes code easier to reason about for both developers and compilers. A function that yields values, for instance, declares a yield effect directly in its signature.
Effect systems pair naturally with effect handlers. The Koka documentation explains that effect handlers “let you define advanced control abstractions, like exceptions, async/await, iterators, parsers, ambient state, or probabilistic programs, as a user library in a typed and composable way,” so new control constructs can be added without changing the language itself.
The motivation is the same one behind purity and referential transparency in functional programming: if effects are tracked in types, a reader can trust that a function marked pure really has no hidden interactions with the outside world, and the type checker enforces that promise.