Motoko Wishlist 2025

The Motoko ecosystem needs specific language features and libraries to become production-ready for serious IC development. While most projects currently default to Rust due to ecosystem maturity, Motoko has strong fundamentals that could make it the preferred choice with the right improvements.

This thread is for specific requests of language features or Motoko libraries that are lacking. The goal is to create a comprehensive reference that can guide development priorities and community library efforts. Keep it focused on concrete technical needs - broader discussion about Motoko’s future and ecosystem strategy should go in the Discussion - What’s Missing for Motoko Adoption? thread.

What to post here:

  • Language features you need for your IC projects
  • Missing libraries that would unlock your use cases
  • Specific gaps preventing you from choosing Motoko

Be specific about what you need and why. This creates a reference for what the community should prioritize building.

What NOT to post here:

  • General discussion or commentary about Motoko’s future
  • Broad ecosystem concerns or strategic questions
  • Debates about priorities or approaches
  • Meta-discussion about the language or community

Categories

  • Language Features: Syntax improvements, type system enhancements, control flow
  • Standard Library: Core data structures, algorithms, utilities
  • Third-party Libraries: HTTP clients, JSON processing, cryptography, testing frameworks
  • IC-Specific Integration: Canister lifecycle management, inter-canister calls, upgrade patterns, cycle management

Previous Context

3 Likes

Here are mine from the previous wishlist linked:

Language Features - Type Reflection / Custom Data Structure Deserialization

Problem: Can’t deserialize to a custom data structure without manual parsing. There’s no way to introspect types at runtime or automatically deserialize JSON/other formats into custom types.

This makes working with external APIs and data formats very verbose - you have to manually parse every field and handle type conversions.

Potential solution: Some form of type reflection or derive macros that can automatically generate serialization/deserialization code for custom types.

Language Features - Error Propagation

The biggest pain point I run into is dealing with stopping code evaluation and returning an #error or continuing on with eval. My code is full of this pattern:

let value = switch(doSomething(...)) {
  case (#error(e)) return #error(e);
  case (#ok(v)) v;
};

Potential solution: Have a built-in Result<T, E> like Rust and handle propagation like null propagation with do ? {}:

let result : Result<T, E> = do E {
  let value1 : T = doSomething(...)*;
  let value2 : T = doSomething(...)*;
  value2;
}

Language Features - Subtyping with Pattern Matching

This is one I didn’t expect with structural typing. I run into this issue regularly and know others have as well.

When I have a Supertype that adds additional functionality on top of an existing type, I want to handle the supertypes cases and ALL of the subtypes. Given this example:

public type SubType = {
  #one;
  #two;
};

public type SuperType = {
  #three;
};

switch (superType) {
  case (#three) processThree();
  case (#two) processSubType(#two);
  case (#one) processSubType(#one);
};

I want it to be less redundant like:

switch (superType) {
  case (#three) processThree();
  // Remaining cases have to be the subtype
  case (subType) processSubType(subType);
};

Reference: Variant subset matching

Language Features - String Interpolation

It’s annoying to write out strings with # and no interpolation:

let value = "This is some " # someToTextFunc(v) # " text that im writing and took me " # Nat.toText(x) # " seconds to come up with";

Potential solution: String interpolation syntax:

let value = $"This is some {someToTextFunc(v)} text that im writing and took me {Nat.toText(x)} seconds to come up with";

I don’t have a good solution for making stringification better because structural typing makes it hard to know how to format values. An option is to make anything that is not Text default to whatever debug_show does, but that might be dangerous and make it easy to make mistakes.

Language Features - Better Type Inference for Inline Functions

A lot of the time I just want to do something like a simple map:

let v : [Nat] = [1, 2, 3];
Array.map(v, func(x) = x + 1);

But the code above doesn’t work because “cannot infer type of variable” is an error. So either the param types/return types have to be defined in the function or on the Array.map. This becomes more and more of a problem with longer type names and more parameters. It seems like it should have enough information to infer, but it isn’t able to.

The func(...) = ... syntax helps vs a normal func but it’s not quite there yet.

4 Likes

Actor modules that I can include and potentially override public shared functions and queries with my own versions(or add code with a super.call.

Ie

import actor "mo:icrc1-mo/token";

//the above adds icrc1_transfer etc to my actor as well as any stable vars, classes, etc....collision my be a big deal here

public query({caller}) override icrc1_balance(args:Account) :Nat{

// private balances
if(args.owner==caller) super.call(args);
else 0;

};
2 Likes

Protobuf support. I’m sort of confused why ledger blocks are protobuf encoded, and yet Motoko doesn’t have strong support for decoding those blocks (unless things have changed since How to get protobuf messsages from ic? - Developers - Internet Computer Developer Forum).

1 Like