diff --git a/doc/examples.xml b/doc/examples.xml
index 242215678..ba6145326 100644
--- a/doc/examples.xml
+++ b/doc/examples.xml
@@ -389,3 +389,50 @@ gap> KnightsGraph(IsMutable, 3, 9);
<#/GAPDoc>
+
+<#GAPDoc Label="HaarGraph">
+
+
+ A digraph.
+
+ If n is a positive integer then this operation returns
+ the Haar graph H(n).
+
+ From
+ https://mathworld.wolfram.com/HaarGraph.html:
+
+
+ A Haar graph H(n) is a bipartite regular vertex-transitive graph
+ indexed by a positive integer and obtained by a simple binary encoding of
+ cyclically adjacent vertices. Haar graphs may be connected or
+ disconnected.
+
+ The number of vertices in the Haar graph H(n) is
+ equal to twice m, where m is the number of digits
+ required to represent n in binary.
+ These vertices are arranged into bicomponents
+ [1..m] and [m+1..2*m].
+ Vertices i and j in different bicomponents are
+ adjacent by a symmetric pair of edges if and only if
+ the binary representation of n has a 1 in position
+ (j-i modulo m) + 1 from the left.
+
+ If the optional first argument filt is present, then this should
+ specify the category or representation the digraph being created will
+ belong to. For example, if filt is ,
+ then the digraph being created will be mutable, if filt is , then the digraph will be immutable.
+ If the optional first argument filt is not present, then is used by default.
+
+ HaarGraph(3);
+
+gap> D := HaarGraph(16);
+
+]]>
+
+
+<#/GAPDoc>
diff --git a/doc/z-chap2.xml b/doc/z-chap2.xml
index 7d4d28826..7beb2b584 100644
--- a/doc/z-chap2.xml
+++ b/doc/z-chap2.xml
@@ -87,6 +87,7 @@
<#Include Label="JohnsonDigraph">
<#Include Label="PetersenGraph">
<#Include Label="GeneralisedPetersenGraph">
+ <#Include Label="HaarGraph">
<#Include Label="KnightsGraph">
<#Include Label="StarDigraph">
diff --git a/gap/examples.gd b/gap/examples.gd
index e3a1e15d6..60f5eec7e 100644
--- a/gap/examples.gd
+++ b/gap/examples.gd
@@ -56,3 +56,7 @@ DeclareOperation("StarDigraph", [IsFunction, IsPosInt]);
DeclareConstructor("KnightsGraphCons", [IsDigraph, IsPosInt, IsPosInt]);
DeclareOperation("KnightsGraph", [IsPosInt, IsPosInt]);
DeclareOperation("KnightsGraph", [IsFunction, IsPosInt, IsPosInt]);
+
+DeclareConstructor("HaarGraphCons", [IsDigraph, IsPosInt]);
+DeclareOperation("HaarGraph", [IsPosInt]);
+DeclareOperation("HaarGraph", [IsFunction, IsPosInt]);
diff --git a/gap/examples.gi b/gap/examples.gi
index b829bd2af..24ba8cafc 100644
--- a/gap/examples.gi
+++ b/gap/examples.gi
@@ -446,3 +446,44 @@ KnightsGraphCons);
InstallMethod(KnightsGraph, "for two positive integers", [IsPosInt, IsPosInt],
{m, n} -> KnightsGraphCons(IsImmutableDigraph, m, n));
+
+InstallMethod(HaarGraphCons,
+"for IsMutableDigraph and a positive integer",
+[IsMutableDigraph, IsPosInt],
+function(filt, n)
+ local m, binaryList, D, i, j;
+ m := Log(n, 2) + 1;
+ binaryList := DIGRAPHS_BlistNumber(n + 1, m);
+ D := EmptyDigraph(IsMutableDigraph, 2 * m);
+
+ for i in [1 .. m] do
+ for j in [1 .. m] do
+ if binaryList[((j - i) mod m) + 1] then
+ DigraphAddEdge(D, [i, m + j]);
+ fi;
+ od;
+ od;
+
+ return DigraphSymmetricClosure(D);
+end);
+
+InstallMethod(HaarGraphCons,
+"for IsImmutableDigraph and a positive integer",
+[IsImmutableDigraph, IsPosInt],
+function(filt, n)
+ local D;
+ D := MakeImmutable(HaarGraphCons(IsMutableDigraph, n));
+ SetIsMultiDigraph(D, false);
+ SetIsSymmetricDigraph(D, true);
+ SetIsRegularDigraph(D, true);
+ SetIsVertexTransitive(D, true);
+ SetIsBipartiteDigraph(D, true);
+ return D;
+end);
+
+InstallMethod(HaarGraph, "for a function and a positive integer",
+[IsFunction, IsPosInt],
+HaarGraphCons);
+
+InstallMethod(HaarGraph, "for a positive integer", [IsPosInt],
+{n} -> HaarGraphCons(IsImmutableDigraph, n));
diff --git a/gap/utils.gd b/gap/utils.gd
index 6dc45dc79..61d352c3c 100644
--- a/gap/utils.gd
+++ b/gap/utils.gd
@@ -23,3 +23,5 @@ DeclareGlobalFunction("DigraphsTestExtreme");
DeclareGlobalFunction("DigraphsTestInstall");
DeclareGlobalFunction("DigraphsTestStandard");
DeclareGlobalFunction("DigraphsTestManualExamples");
+
+DeclareGlobalFunction("DIGRAPHS_BlistNumber");
diff --git a/gap/utils.gi b/gap/utils.gi
index 0bc647dfd..8ae2f37af 100644
--- a/gap/utils.gi
+++ b/gap/utils.gi
@@ -555,3 +555,21 @@ DIGRAPHS_CheckManualConsistency := function()
DIGRAPHS_CheckDocCoverage(doc);
return DIGRAPHS_CheckManSectionTypes(doc, true);
end;
+
+InstallGlobalFunction(DIGRAPHS_BlistNumber,
+function(nr, n)
+ local x, q, i;
+
+ x := BlistList([1 .. n], []);
+ nr := nr - 1; # to be in [0 .. 2 ^ n - 1]
+ for i in [n, n - 1 .. 1] do
+ q := nr mod 2;
+ if q = 0 then
+ x[i] := false;
+ else
+ x[i] := true;
+ fi;
+ nr := (nr - q) / 2;
+ od;
+ return x;
+end);
diff --git a/tst/standard/examples.tst b/tst/standard/examples.tst
index c281eb55e..c15910428 100644
--- a/tst/standard/examples.tst
+++ b/tst/standard/examples.tst
@@ -252,6 +252,28 @@ false
gap> KnightsGraph(IsMutable, 3, 9);
+# DIGRAPHS_HaarGraph
+gap> HaarGraph(1);
+
+gap> OutNeighbours(last);
+[ [ 2 ], [ 1 ] ]
+gap> HaarGraph(2);
+
+gap> OutNeighbours(last);
+[ [ 3 ], [ 4 ], [ 1 ], [ 2 ] ]
+gap> HaarGraph(3);
+
+gap> OutNeighbours(last);
+[ [ 3, 4 ], [ 3, 4 ], [ 1, 2 ], [ 1, 2 ] ]
+gap> D := HaarGraph(16);
+
+gap> IsBipartiteDigraph(D);
+true
+
#
gap> DIGRAPHS_StopTest();
gap> STOP_TEST("Digraphs package: standard/examples.tst", 0);