Clean

Clean was developed at Radboud University Nijmegen from 1987. It looks and behaves much like Haskell: pure, lazy and statically typed. It solves the effects problem differently, through uniqueness types instead of monads.

Paradigm: Functional Programming

What Makes Clean Special

  • Uniqueness types. A value marked unique (*World, *File) is guaranteed to have exactly one reference. The compiler then allows safe in-place updates, so I/O stays pure without monads.
  • Graph rewriting. Clean programs are evaluated by rewriting graphs of expressions, which shares sub-results naturally and helps efficient lazy evaluation.
  • Fast native code. The compiler produces efficient executables, and the language was long known as one of the fastest lazy functional implementations.
  • Generic programming. You can write functions over the structure of any type, and it powers automatic serialization and pretty printing.
  • A friendly IDE. It ships with an integrated environment. The iTask system builds workflow applications.

Example: The first ten primes

module primes

import StdEnv

primes :: [Int]
primes = sieve [2..]
where
    sieve [p:xs] = [p : sieve [x \\ x <- xs | x mod p <> 0]]

Start :: [Int]
Start = take 10 primes

How It Works

  • The module name must match the file: this code lives in primes.icl. StdEnv is the standard library.
  • The syntax is close to Haskell's: [2..] is an infinite lazy list, and [p:xs] matches the head and tail of a list.
  • The comprehension uses \\ in place of Haskell's | to separate the result from the generators, and | ... as a guard. <> means "not equal".
  • Start is the program entry point and its value is printed: [2,3,5,7,11,13,17,19,23,29].

History and Where It Is Used

Clean is used mainly in research and teaching at universities in the Netherlands and beyond. It has a small community, but it remains an excellent way to study lazy functional programming and to compare uniqueness types with monads and with Rust's ownership, which is related.

Learn More