# MicroHs v0.15.0.0

**URL:** <https://discourse.haskell.org/t/microhs-v0-15-0-0/13422>\
**Category:** Announcements\
**Created:** [December 17, 2025, 10:20pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422 "2025-12-17T22:20:53Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![augustss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/augustss/32/887_2.png) [@augustss](https://discourse.haskell.org/u/augustss)\
**Post date:** [December 17, 2025, 10:20pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/1 "2025-12-17T22:20:53Z")

</div>

There is a new version of [MicroHs on GitHub](https://github.com/augustss/MicroHs).  
There are lots of little changes, and more packages on Hackage now compile.

Release notes:

## Features

- New language extensions
  - EmptyDataDeriving
  - NondecreasingIndentation
  - MonoLocalBinds removed
  - MonomorphismRestriction

- Evaluation stats in interactive system: `set +s`
- STM (implementation from David Sabel)
- GHC compatible exception handling (`mask` etc.)
- `System.Mem.Weak`
- `Foreign.StablePtr`
- `out.comb` can be generated compressed and base64 encoded
- Improved `Data.ByteString`
- FFI wrapper for `eval.c`
- New `BFILE` stuff: file descriptor, buffering, base64 coding
- `Double` and `Float` are now different types
- `Int64`/`Word64` on 32 bit platforms
- Instruction counts on supported platforms (MacOS&M4, Linux&x86\_64)
- Proper `array` package
- Unboxed tuple and sum syntax accepted (but no unboxing)
- Deriving `Data`, `Foldable`, `Functor`, `Ix`, `Read`, `Traversable`

## Performance

- Evaluation in the interactive system is much faster

## FFI

- `foreign export ccall` implemented
- `foreign import javascript` implemented
- JavaScript version of the MicroHs runtime is part of the distribution: `generated/mhseval.js`

## Bug fixes

- Lots

## Packages

- Many more packages compile, e.g., QuickCheck, filepath
- See [MicroHs hackage compilation - Google Sheets](https://docs.google.com/spreadsheets/d/1e0dbUg5uuFKNwgMpwtBnYRldPCYYyBqYfsbyhEjf5bU/edit?usp=sharing)
- Use `make -f Makefile.packages` to install some of them

## Contributors

- Ben Clifford [benc@hawaga.org.uk](mailto:benc@hawaga.org.uk)
- Heinrich Apfelmus [apfelmus@quantentunnel.de](mailto:apfelmus@quantentunnel.de)
- Henning Thielemann [git@henning-thielemann.de](mailto:git@henning-thielemann.de)
- konsumlamm [konsumlamm@gmail.com](mailto:konsumlamm@gmail.com)
- Lorenzo Tabacchini [lortabac@gmx.com](mailto:lortabac@gmx.com)
- Thomas Mahler [thma32@web.de](mailto:thma32@web.de)
- Thomas van Maaren [74723259+tvmaaren@users.noreply.github.com](mailto:74723259+tvmaaren@users.noreply.github.com)
- Tristan de Cacqueray [tristan@midirus.com](mailto:tristan@midirus.com)

---

<div class="post-metadata">

**Author:** ![ashokkimmel](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ashokkimmel/32/5111_2.png) [@ashokkimmel](https://discourse.haskell.org/u/ashokkimmel)\
**Post date:** [December 18, 2025, 5:57pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/2 "2025-12-18T17:57:27Z")

</div>

Very impressive, I’m just wondering  
You’ve implemented so many features that I almost wonder wich things are not yet supported?  
How much does performance compare with GHC?  
Is it better designed than GHC? Easier to modify, less complicated? Does it use the same pipeline?

---

<div class="post-metadata">

**Author:** ![danidiaz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/danidiaz/32/92_2.png) [@danidiaz](https://discourse.haskell.org/u/danidiaz)\
**Post date:** [December 18, 2025, 7:28pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/3 "2025-12-18T19:28:49Z")

</div>

> [@augustss](#):
>
> MonoLocalBinds removed

I thought MonoLocalBinds were a requirement for GADTs!

---

<div class="post-metadata">

**Author:** ![augustss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/augustss/32/887_2.png) [@augustss](https://discourse.haskell.org/u/augustss)\
**Post date:** [December 18, 2025, 9:21pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/4 "2025-12-18T21:21:50Z")

</div>

There are some things missing from MicroHs:

- Type families; needed for many things, e.g., generics. I plan to implement it.
- Template Haskell. Nope, won’t happen
- Quantified constraints. Yes, coming.
- Implicit parameters. Nope.

Is it better designed than GHC? I don’t know.

Is it easier to modify? I think so, but that’s for others to answer.

Does it use the same pipeline? It’s a compiler, so some things are similar, some are different.

---

<div class="post-metadata">

**Author:** ![augustss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/augustss/32/887_2.png) [@augustss](https://discourse.haskell.org/u/augustss)\
**Post date:** [December 18, 2025, 9:24pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/5 "2025-12-18T21:24:37Z")

</div>

The worst that can happen without `MonoLocalBinds` is that you get an unexpected type error and have to add a type signature.

I would have liked to keep `MonoLocalBinds`, but a lot of packages rely on local bindings to be generalized. Given how reluctant some package maintainers are to accept my changes, I’ve given in.

---

<div class="post-metadata">

**Author:** ![ashokkimmel](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ashokkimmel/32/5111_2.png) [@ashokkimmel](https://discourse.haskell.org/u/ashokkimmel)\
**Post date:** [January 5, 2026, 5:22am UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/6 "2026-01-05T05:22:34Z")

</div>

By pipeline I mean parser, renamer, type checker, core, stg, cmm…

---

<div class="post-metadata">

**Author:** ![augustss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/augustss/32/887_2.png) [@augustss](https://discourse.haskell.org/u/augustss)\
**Post date:** [January 5, 2026, 7:04am UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/7 "2026-01-05T07:04:08Z")

</div>

Here’s the pipeline

- lexer, a state machine delivering tokens
- parser, using classical parser combinators
- typechecking
  - inserts dictionaries
  - desugers a little, e.g., do-notation
  - output is the same AST data type as input
  - several passes
    - kind check all types
    - generate deriving instances
    - turn classes and instances into regular definitions
    - typecheck values

- desugaring
  - remove list comprehension
  - turn complex pattern matching into simple pattern matching
  - encode constructors/case to lambda expressions
  - some minor optimizations
    - remove let-bindings used 0 or 1 time
    - introduce local recursive functions

  - output language is lambda calculus + literals, just 4 constructors
    - variables
    - application
    - lambda
    - literals, i.e., numbers, bytestrings, primitive functions, FFI functions

- bracket abstraction, i.e., get rid of lambdas by using combinators
- serialize output

Done. The type checker is by far the most complex piece.

Edit: There is no separate renaming pass. I think having that is a mistake.

---

<div class="post-metadata">

**Author:** ![chrisdone](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chrisdone/32/1408_2.png) [@chrisdone](https://discourse.haskell.org/u/chrisdone)\
**Post date:** [January 5, 2026, 1:15pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/8 "2026-01-05T13:15:40Z")

</div>

> [@augustss](#):
>
> There is no separate renaming pass. I think having that is a mistake.

Oh, interesting—as someone who enjoys compiler pipelines, tell me more!

---

<div class="post-metadata">

**Author:** ![sclv](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/sclv/32/71_2.png) [@sclv](https://discourse.haskell.org/u/sclv)\
**Post date:** [January 5, 2026, 7:05pm UTC](https://discourse.haskell.org/t/microhs-v0-15-0-0/13422/9 "2026-01-05T19:05:00Z")

</div>

We made the same no renamer pass in our in-house language at work. Its a very mixed bag – we certainly can get away without it. (But in part because we’ve got a goofy namespacing hack instead of proper modules). Usually it feels good to avoid an extraneous pass, and it simplifies the code. On occasion we have to work around the lack of a renamer with pushing various resolution functionality either down into the parser layer or up into the typechecking and evaluator layers, and sometimes all three, and subtle bugs can be introduced at which point I start cursing about “if only we weren’t too lazy to write a renamer”.
