Here is a simple implementation:
Protect[qCO, qDO];
qOperatorQ[expr_] := MatchQ[expr, qCO | qDO | Ket[n_Integer]];
(* take scalars out *)
CenterDot[left___, Times[scalar_?NumericQ, op_?qOperatorQ], right___] := Times[
scalar,
CenterDot[left, op, right]
];
(* Implement commutation relations *)
CenterDot[left___, qDO, qCO, right___] := Plus[
CenterDot[left, qCO, qDO, right],
CenterDot[left, right]
];
(* Allow to use powers of operators *)
CenterDot[left___, Power[op : (qCO | qDO), n_Integer], right___] := CenterDot[
left,
Sequence @@ ConstantArray[op, n],
right
];
(* effective OneIdentity attribute *)
CenterDot[op_?qOperatorQ] := op;
(* implement action on Fock states *)
CenterDot[left___, qDO, Ket[0]] := 0;
CenterDot[left___, qCO, Ket[n_Integer]] := Times[
Sqrt[n + 1],
CenterDot[left, Ket[n + 1]]
];
CenterDot[left___, qDO, Ket[n_Integer]] := Times[
Sqrt[n],
CenterDot[left, Ket[n - 1]]
];
I used CenterDot to denote the operator product (note that you can write a CenterDot product with the shortcut [esc].[esc]), qCO to denote the creation operator $a^\dagger$, qDO for the destruction operator $a$, and the built-in symbol Ket[n] to denote the Fock basis state $\lvert n \rangle$ (which can be inserted with [esc]ket[esc]).
You can of course change this notation as you like.
Here are a couple of examples of how to use the above (I here keep the full and ugly description of the operators to more clearly show what symbols are being used. Note that you can insert the SuperDagger with a[ctrl+^][esc]dg[esc]):
a = qDO;
SuperDagger[a] = qCO;
a[CenterDot]Ket[2]
a[CenterDot]a[CenterDot]Ket[2]
a^2[CenterDot]Ket[2]
a[CenterDot]a[CenterDot]a[CenterDot]Ket[2]
a[CenterDot]SuperDagger[a][CenterDot]a[CenterDot]Ket[2]
a[CenterDot](SuperDagger[a])^4[CenterDot]a[CenterDot]Ket[2]
k, it is simple:a[k_] := DiagonalMatrix[ConstantArray[1, k-1], k, -1]and $a^\dagger$ is then automatically defined. – rcollyer Mar 17 '17 at 12:15a[k_] := DiagonalMatrix[Sqrt /@ Range[1, k - 1], 1, k]. – Saurabh Shringarpure Feb 16 '24 at 03:12