Flix (programming language)

This is an old revision of this page, as edited by JorKadeen (talk | contribs) at 09:31, 30 August 2020 (Extensible Records). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Flix is a functional, imperative, and logic programming language developed at Aarhus University with funding from the Independent Research Fund Denmark[2] and by a community of open source contributors. Flix supports algebraic data types, pattern matching, parametric polymorphism, currying, higher-order functions, extensible records[3], channel and process-based concurrency, and tail call elimination.

Flix
ParadigmMulti-paradigm: functional, imperative, logic
DeveloperAarhus University, open-source contributors
First appeared10 August 2015; 10 years ago (2015-08-10)
Typing disciplineinferred, static, strong
PlatformJVM
LicenseApache License 2.0[1]
Filename extensions.flix
Websiteflix.dev
Influenced by
F#, Go, Haskell, OCaml, Scala

Flix supports Datalog constraints as first-class values entities. A Datalog constraint set, i.e. a set of Datalog facts and rules, can be passed to and returned from functions, stored in data structures, and composed with other Datalog constraint sets. The minimal model of a Datalog constraint set can be computed which is itself another Datalog constraint set. In this way, Flix can be used as a statically-typed meta-programming language for Datalog where Datalog programs are constructed and solved at run-time. Flix also supports stratified negation and its type system ensures that such programs are stratified at compile-time.

The Flix type and effect system supports Hindley-Milner-style type inference. In addition to ensuring standard type safety, the type and effect system separates pure and impure code: if an expression is typed as pure then it cannot produce an effect. Higher-order functions can enforce that they are given pure function arguments. Higher-order functions that accept both pure and impure function values can be declared as effect polymorphic in the effect of their arguments. The effect inference algorithm is based on Boolean unification.

Features

The syntax of Flix is inspired by Scala. The type system is based on Hindley-Milner which has been used in a wide variety of functional programming languages, including OCaml, Haskell, and Standard ML. The concurrency model of Flix is based on channels and processes.

The Flix compiler compiles programs to JVM bytecode which is executable on the Java Virtual Machine (JVM). The compiler performs whole program compilation, eliminates polymorphism using monomorphization[4], and uses tree shaking to remove unused code. The use of monomorphization avoids boxing of primitive types at the cost of longer compilation times and larger binaries.

Flix supports full tail call elimination[5] which ensures that calls in tail position never consume stack space. Since the JVM instruction set does not support tail calls, such calls are emulated using a form of reusable stack frames[6].

Examples

Hello World

The following program prints Hello World when compiled and executed:

def main(): Unit & Impure = 
    Console.printLine("Hello World")

The type and effect signature of the main function specifies that it takes no parameters, returns a value of type Unit, and that the function is impure. The main is impure because it invokes the printLine which causes an effect.

Algebraic Data Types and Pattern Matching

The following program fragment declares an algebraic data type (ADT) named Shape:

enum Shape {
    case Circle(Int),        // has circle radius
    case Square(Int),        // has side length
    case Rectangle(Int, Int) // has height and width
}

The ADT has three constructors: Circle, Square, and Rectangle.

The following program fragment uses pattern matching to destruct a Shape value:

def area(s: Shape): Int = match s {
    case Circle(r)       => 3 * (r * r)
    case Square(w)       => w * w
    case Rectangle(h, w) => h * w
}

Higher-Order Functions

The following program fragment defines a higher-order function twice that when given a function f from Int to Int returns a function that applies f to its input two times:

def twice(f: Int -> Int): Int -> Int = x -> f(f(x))

We can use the function twice as follows:

twice(x -> x + 1)(0)

Here the call to twice(x -> x + 1) returns a function that will increment its argument two times. Consequently, the result of the entire expression is 0 + 1 + 1 = 2.

Parametric Polymorphism

...

Extensible Records

...

Notable Features

Polymorphic Effects

...

First-class Datalog Constraints

...

Principles

The Flix language design includes a collection of stated principles that shape the language[7]. These include:

  • Everything is an expression.
  • Separation of pure and impure code.
  • Closed-world assumption.

The principles states that dead or redundant code is a code smell and hence disallows:

  • Unused functions.
  • Unused parameters, types, and variables.
  • Variable shadowing.

The principles also list several programming language features have been deliberately omitted. In particular, Flix has:

  • No null values. Instead the use of the Option data type is recommended.
  • No implicit coercions. Instead type conversions must be inserted explicitly by the programmer.
  • No reflection.
  • No compiler warnings, only compiler errors.

References

  1. ^ "Apache License 2.0" – via GitHub.
  2. ^ "Forskningsprojekter". Danmarks Frie Forskningsfond (in Danish).
  3. ^ Leijen, Daan. "Extensible records with scoped labels". Trends in Functional Programming.
  4. ^ "Monomorphise". mlton.org.
  5. ^ Madsen, Magnus; Zarifi, Ramin; Lhoták, Ondřej (2018). "Tail call elimination and data representation for functional languages on the Java virtual machine". Proceedings of the 27th International Conference on Compiler Construction - CC 2018: 139–150. doi:10.1145/3178372.3179499.
  6. ^ Tauber, Tomáš; Bi, Xuan; Shi, Zhiyuan; Zhang, Weixin; Li, Huang; Zhang, Zhenrui; Oliveira, Bruno C. D. S. (2015). "Memory-Efficient Tail Calls in the JVM with Imperative Functional Objects". Programming Languages and Systems. 9458: 11–28. doi:10.1007/978-3-319-26529-2_2.
  7. ^ "The Flix Programming Language - Principles". flix.dev. Retrieved 28 August 2020.

Category:Functional languages