Open-source project
vekatze/neut avatar
vekatze/neut

Neut: a functional language where the types decide the memory

A functional programming language with static memory management

1,010 stars16 forksHaskellMIT

At a glance

What is it?
Neut is a functional programming language with static memory management, where the type of a value determines how it is stored, so there is no collector to tune and no annotation to write to get either the type checking or the memory behaviour. It suits someone who wants the guarantees of a statically typed functional language without a garbage collector, and it is a young language with a small ecosystem.
Who is it for?
Adopt Neut if you want functional programming with predictable memory and no garbage collector, because the type system is what allocates, and the compiler emits LLVM IR and native binaries rather than an intermediate runtime. Do not adopt it for a project that needs a large library ecosystem, since the language is young and the ecosystem is small, and expect the call by value, impure core to be different from what a pure functional language gives you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 35 days ago.
What is it written in?
Mainly Haskell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the language is

Neut is a functional programming language with static memory management, and that phrase is the whole pitch.

The key features are listed in three lines and they build on each other. There is full lambda-calculus support, so the language is not a restricted functional subset but the real thing. There is predictable, type-directed memory management, which is what distinguishes it from the usual arrangement. And there are no extra type annotations needed to achieve both of the above, which is the part that makes the first two usable in practice.

That third point is the difficult one. A type-directed memory system needs the compiler to know, at every allocation site, whether a value is going to live on the heap or not, and in a language with full higher type polymorphism that means the type system has to carry more information than a conventional one. Requiring the programmer to write that information as annotations is the easy way out. Neut's claim is that it does not need to, and the type system description gives the reason.

The project is by Vekatzes, it is written in Haskell, the licence is MIT, and the last push to the repository was on 2026-09-20. The recent releases are 0.18.1 from May 2026, 0.18.0 from April 2026 and 0.17.22 from July 2025.

The type system, and what the box modality does

The type system is described in one line, and it is a line worth unpacking.

The readme gives it as approximately System Fω with algebraic data types, recursion and a box modality, and then says the obvious thing about it: that is the usual one in functional programming, but a bit generalized.

System Fω is the type system with kinds and type operators, so you can write types that take other types as parameters, and the algebraic data types are the sum and product types that every functional language has. Recursion in the type system is what allows the fixed point combinator to be typed without a bottom type, and the box modality is the piece that is specific here.

A modality on a type is a qualification of what that type may be used in, and the box modality is the qualifier that says where a value lives. That is the connection to the memory story, because a modality that tells the compiler where something is stored is what lets memory management be type-directed rather than a runtime decision. The phrase a bit generalized is doing quiet work in that sentence, and the documentation site is where the details are.

The result is that a program in Neut gets the same guarantees as a statically typed functional language, plus a memory layout that is decided before the program runs, and the whole thing is inferred from the types the programmer already wrote.

Call by value, and impure

Two of the basic characteristics are worth pausing on, because they set Neut apart from the functional languages people usually meet.

It is call by value. That is a deliberate choice, and it is the choice that makes the memory model tractable, because a value's location and ownership are decided at the point where the value is created rather than being a question the runtime answers later. It also means the usual functional argument about referential transparency and the cost of copying does not apply in the same form, since there is no sharing of mutable structure to begin with.

And it is impure. The readme says so as a bullet point, without apologising, and that is arguably the more interesting of the two.

Impurity in a functional language is usually a compromise, something the language supports so you can write imperative code when you need it. In Neut it looks more like a design decision, and the reason is visible in the rest of the feature list. The language has built-in rapid prototyping support of the kind found in scripting languages, and a built-in formatter. Both of those are features you would not normally expect from a purely functional, statically typed language, and both point the same way, which is at a language that can be used for small scripts as readily as for programs.

So Neut is a functional core with a call by value, impure, statically typed design, and the impurity is what lets the scripting experience work without the type system being abandoned.

The toolchain: LLVM, a formatter and an editor

The build target is LLVM IR and native binaries, so a Neut program is compiled rather than interpreted, and the output is something you can ship as a binary rather than something that needs a runtime alongside it.

Three developer tools come built in, and they are the reason the language is usable day to day.

The formatter is built in, which is a small decision with a large effect on a language people actually write in. A formatter in the distribution means nobody has to install one, and it means formatting decisions are made once by the language rather than by whichever tool the author happened to have.

There is built-in LSP support, with a showcase page for it on the documentation site, so an editor can get completion and diagnostics from the language itself rather than from a separate analysis tool that has to be kept in step with the compiler.

And there is built-in rapid prototyping support of the kind found in scripting languages, which is the feature that connects the impure design to the practical workflow. A language with a compiler, a formatter and an editor integration can be used for a five line script and for a large program without changing tools.

The compilation target is what makes the performance story plausible, and it also means the language sits in a well trodden ecosystem of back ends rather than inventing its own.

The repository, and how it is built

The layout tells you the shape of the project, and the directory names are the interesting part.

There is a neut directory and a src directory, which is the usual split between the language itself and the compiler that implements it. There is a book directory, which is the documentation source, and a test directory for the test suite, plus a build directory and a licenses directory with the third party licence texts and a licence file for the project itself.

The build tooling is Haskell, with a stack configuration and its lock file, which is how a Haskell project of this kind is normally built. There is also a justfile, so the everyday tasks are run through a task runner, and a hie configuration, which is the file that makes the project work with the Haskell language server, and a script to install it.

The continuous integration is worth noting because of the platforms. There are separate test workflows for Linux, for macOS and for WebAssembly, each with its own badge.

Running the test suite on WebAssembly is the interesting one. A language with a static memory model and a compiler backend is a natural fit for a WebAssembly target, because WebAssembly is itself a language with a linear memory model, and the fact that the test suite runs there is evidence that the memory model is not tied to a particular operating system's allocator.

The project page carries the documentation, and the readme is brief by design, with a pointer to the site rather than a duplicate of it.

Where it fits, and what the state of the project is

The alternative to a language like this is a conventional functional language with a garbage collector, and the difference in approach is exactly what the memory model changes.

With a collector, memory is a runtime concern. The allocation rate, the live set and the pause behaviour of the collector are all things you tune and measure, and a program that allocates a lot in a hot loop has a cost you cannot remove from the source. With type-directed allocation, the decision is made where the value is created, and a value that cannot escape is a value that does not need a heap, and that is a property you can see in the source rather than in a profile.

The price is the type system. The box modality and the generalisation of the usual functional type system are what buy the memory behaviour, and they make the type system of Neut different from what a Haskell or ML programmer expects. A port is not mechanical, and the documentation site is where the details of that live.

On the state of the project, the release numbers tell the story. 0.18.1 in May 2026, 0.18.0 in April 2026, and 0.17.22 in July 2025, with pushes continuing into September 2026. The version is below one, which says the language is still changing shape, and that is the main risk for anyone planning to build on it.

So the honest summary is that Neut is an interesting and actively developed experiment in what a functional language can be when the allocator is part of the type system, with a toolchain that takes it seriously, and with an ecosystem that has not caught up yet.

Editorial conclusion

Adopt Neut if you want functional programming with predictable memory and no garbage collector, because the type system is what allocates, and the compiler emits LLVM IR and native binaries rather than an intermediate runtime. Do not adopt it for a project that needs a large library ecosystem, since the language is young and the ecosystem is small, and expect the call by value, impure core to be different from what a pure functional language gives you. Before you start, read the documentation site, because the memory model is explained there and it is the part you will have to internalise.

Frequently asked questions

What is Neut?

It is a functional programming language with static memory management. Its key features are full lambda-calculus support, predictable type-directed memory management, and no extra type annotations needed to achieve either of the other two. It is call by value, impure, and compiles to LLVM IR and native binaries.

What type system does Neut use?

The readme describes it as approximately System Fω with algebraic data types, recursion and a box modality, which it calls the usual functional programming type system but a bit generalized. The generalization is what allows memory management to be decided by the types.

Which developer tools come with Neut?

There is a built-in formatter, built-in LSP support with a showcase page on the documentation site, and built-in rapid prototyping support of the kind found in scripting languages. The compiler targets LLVM IR and native binaries.

How is the Neut project built and tested?

The compiler is written in Haskell and built with stack, with a justfile for the everyday tasks and a configuration for the Haskell language server. The continuous integration runs separate test workflows for Linux, for macOS and for WebAssembly, so the memory model is exercised on a platform that is not an operating system at all.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. vekatze/neut on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vekatze-neut.svg)](https://hysenlabs.com/projects/vekatze-neut)

Was this useful?