Demonstrate in your programming language the following:

Construct a Maybe Monad by writing the 'bind' function and the 'unit' (sometimes known as 'return') function for that Monad (or just use what the language already has implemented)
Make two functions, each which take a number and return a monadic number, e.g. Int -> Maybe Int and Int -> Maybe String
Compose the two functions with bind


A Monad is a single type which encapsulates several other types, eliminating boilerplate code. In practice it acts like a dynamically typed computational sequence, though in many cases the type issues can be resolved at compile time.

A Maybe Monad is a monad which specifically encapsulates the type of an undefined value.

 
program Maybe_monad;
 
{$APPTYPE CONSOLE}
 
uses
  System.SysUtils;
 
type
  TmList = record
    Value: PInteger;
    function ToString: string;
    function Bind(f: TFunc<PInteger, TmList>): TmList;
  end;
 
function _Unit(aValue: Integer): TmList; overload;
begin
  Result.Value := GetMemory(sizeof(Integer));
  Result.Value^ := aValue;
end;
 
function _Unit(aValue: PInteger): TmList; overload;
begin
  Result.Value := aValue;
end;
 
{ TmList }
 
function TmList.Bind(f: TFunc<PInteger, TmList>): TmList;
begin
  Result := f(self.Value);
end;
 
function TmList.ToString: string;
begin
  if Value = nil then
    Result := 'none'
  else
    Result := value^.ToString;
end;
 
function Decrement(p: PInteger): TmList;
begin
  if p = nil then
    exit(_Unit(nil));
  Result := _Unit(p^ - 1);
end;
 
function Triple(p: PInteger): TmList;
begin
  if p = nil then
    exit(_Unit(nil));
  Result := _Unit(p^ * 3);
end;
 
var
  m1, m2: TmList;
  i, a, b, c: Integer;
  p: Tarray<PInteger>;
 
begin
  a := 3;
  b := 4;
  c := 5;
  p := [@a, @b, nil, @c];
 
  for i := 0 to High(p) do
  begin
    m1 := _Unit(p[i]);
    m2 := m1.Bind(Decrement).Bind(Triple);
 
    Writeln(m1.ToString: 4, ' -> ', m2.ToString);
  end;
  Readln;
end.