g | x | w | all
Bytes Lang Time Link
060C++20 gcc240925T201656ZG. Sliep
037OCaml240925T225024ZDaniel S
001Javascript240925T175656Zcorvus_1
022Haskell240917T151809Zpxeger

C++20 (gcc), 60 bytes

template<class T>struct M{T t;auto b(auto f){return f(t);}};

Where M is the monad, which allows types to be constructed by instantiating the template:

using Type = M<int>;

Values can be wrapped by using the converting constructor which is generated by the compiler automatically:

auto value = Type{42};

Although thanks to template argument deduction it's also possible to just write auto value = M{42}. And binding works by calling the member function b():

auto value_squared = value.b([](auto x){ return M{x * x}; });

Try it online! (Except at the time of writing, TIO is using an old version of GCC that doesn't fully support C++20 yet.)

OCaml, 37 bytes

type 'a m=M;;let u x=M;;let b x f=M;;

This implements a single-valued monad with constructor u and bind operation b.

And for an example of a non-trivial monad, let's see Reader<int> monad in 53 bytes:

type 'a m=int->'a;;let u x _=x;;let b x f s=f(x s)s;;

Javascript, 1 byte

0

This monad is isomorphic to Identity (). All values of the monad are 0.

The expression 0 defines a "function" with zero arguments (as in Haskell) that works as both unit and bind. As pxeger noted, this bends our rules very much, but I think it's still fun to think about, so I posted this.

Haskell, 22 bytes

data M t=R t
R x%f=f x

Attempt This Online!

First, a definitely-correct answer. This is the identity monad: the type constructor is called M, the unit constructor is called R, and the bind combinator is called (%).

I defined a Monad instance in the footer to demonstrate that the operations have the correct types. I hope it's clear why the monad laws hold.


Pure Haskell, 12 bytes

data M t
z=z

Attempt This Online!

By "pure" I mean with no exceptions and no unsafePerformIO etc.

Highly debatable, but I think it's technically valid. My type constructor is called M (the resulting type just happens to have no values), my unit constructor is called z, and my bind combinator is also called z. Here's my proof of the monad laws:

  1. We must prove z(z(x), f) <-> f(x). If f has type a -> M b for some a and b, then since there are no values of type M b, f must never return (and since we're in "pure" Haskell, f must be a simple infinite loop). Likewise z(z(x), f) will never return because z will enter an infinite loop, so the two expressions are equivalent.

  2. We must prove z(x, z) <-> x. Similarly to the above, x has the type M a for some a, which means evaluating x will never return. Equally, z(x, z) will never return, so they're equivalent.

  3. Very similar.


Pure, halting Haskell, 22 bytes

data M t=R
r _=R
_%_=R

Attempt This Online!

Another silly one. This requires that f has no side effects and always halts.


In fact, since not taking input at all is a valid standard I/O method, you could just have this:

Pure, halting Haskell, 10 bytes

data M t=R

Attempt This Online!

Here, my type constructor is called M, my unit constructor is called R (just make sure not to pass it any arguments), and my bind combinator is also called R (also no need to pass the arguments).


If I can argue this "I/O method" is allowed for the 3rd monad, maybe you can argue that this alone is valid for the 2nd monad? unit and bind take input by... not being called at all?

data M t

There's probably room for some more silly-but-valid Monads. But here's a non-trivial one - the Option monad:

Haskell, 30 bytes

data M t=N|R t
N%_=N
R t%f=f t

The unit constructor is called R, and the bind combinator is called (%).

Attempt This Online!