| Bytes | Lang | Time | Link |
|---|---|---|---|
| 060 | C++20 gcc | 240925T201656Z | G. Sliep |
| 037 | OCaml | 240925T225024Z | Daniel S |
| 001 | Javascript | 240925T175656Z | corvus_1 |
| 022 | Haskell | 240917T151809Z | pxeger |
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
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
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:
We must prove
z(z(x), f) <-> f(x). Iffhas typea -> M bfor someaandb, then since there are no values of typeM b,fmust never return (and since we're in "pure" Haskell,fmust be a simple infinite loop). Likewisez(z(x), f)will never return becausezwill enter an infinite loop, so the two expressions are equivalent.We must prove
z(x, z) <-> x. Similarly to the above,xhas the typeM afor some a, which means evaluatingxwill never return. Equally,z(x, z)will never return, so they're equivalent.Very similar.
Pure, halting Haskell, 22 bytes
data M t=R
r _=R
_%_=R
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
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 (%).