diff --git a/horizon.dhall b/horizon.dhall
index c4687849e3d5b8a7965144cf6cbc163759698e5f..734222a7b731eac55ba65b1891b77e050456c35e 100644
--- a/horizon.dhall
+++ b/horizon.dhall
@@ -185,6 +185,8 @@ let packages =
       , extended-reals = H.callHackage "extended-reals" "0.2.4.0"
       , fast-math = H.callHackage "fast-math" "1.0.2"
       , fcf-containers = H.callHackage "fcf-containers" "0.8.2"
+      , fgl = H.callHackage "fgl" "5.8.2.0"
+      , fgl-arbitrary = H.callHackage "fgl-arbitrary" "0.2.0.6"
       , filelock = H.callHackage "filelock" "0.1.1.7"
       , filemanip = H.callHackage "filemanip" "0.3.6.3"
       , filepattern = H.callHackage "filepattern" "0.1.3"
@@ -255,6 +257,7 @@ let packages =
           H.callHackage "ghc-typelits-natnormalise" "0.7.9"
       , githash = H.callHackage "githash" "0.1.7.0"
       , gitrev = H.callHackage "gitrev" "1.3.1"
+      , graphviz = H.callHackage "graphviz" "2999.20.2.0"
       , gridtables = H.callHackage "gridtables" "0.1.0.0"
       , groups = H.callHackage "groups" "0.5.3"
       , gtk2hs-buildtools = H.callHackage "gtk2hs-buildtools" "0.13.10.0"
@@ -388,6 +391,7 @@ let packages =
       , mersenne-random-pure64 =
           H.callHackage "mersenne-random-pure64" "0.2.2.0"
       , mfsolve = H.callHackage "mfsolve" "0.3.2.2"
+      , microbench = H.callHackage "microbench" "0.1"
       , microlens-aeson = H.callHackage "microlens-aeson" "2.5.1"
       , microlens-ghc = H.callHackage "microlens-ghc" "0.4.14.2"
       , microlens-platform = H.callHackage "microlens-platform" "0.4.3.4"
@@ -486,6 +490,8 @@ let packages =
       , quickcheck-arbitrary-adt =
           H.callHackage "quickcheck-arbitrary-adt" "0.3.1.0"
       , quickcheck-assertions = H.callHackage "quickcheck-assertions" "0.3.0"
+      , quickcheck-state-machine =
+          H.callHackage "quickcheck-state-machine" "0.8.0"
       , quickcheck-text = H.callHackage "quickcheck-text" "0.1.2.1"
       , quote-quot = H.callHackage "quote-quot" "0.2.1.0"
       , random-bytestring = H.callHackage "random-bytestring" "0.1.4"
@@ -662,6 +668,7 @@ let packages =
       , wide-word = H.callHackage "wide-word" "0.1.6.0"
       , with-utf8 = H.callHackage "with-utf8" "1.0.2.4"
       , wizards = H.callHackage "wizards" "1.0.3"
+      , wl-pprint-text = H.callHackage "wl-pprint-text" "1.2.0.2"
       , word-compat = H.callHackage "word-compat" "0.0.6"
       , wreq = H.callHackage "wreq" "0.5.4.2"
       , wuss = H.callHackage "wuss" "2.0.1.5"
diff --git a/horizon.lock b/horizon.lock
index 259f615af9ea797db78f055264dd3284f1eb8f7b..2581a096c34a02d0254fb392c4dbdd6b9165179e 100644
--- a/horizon.lock
+++ b/horizon.lock
@@ -586,6 +586,14 @@
   , mapValue =
       "5283f5c394d622ad8bcb42326a9d93e69fc185c588cb9f01b38da4d82b0811f8"
   }
+, { mapKey = "fgl"
+  , mapValue =
+      "2cb35ba3a1377718b018f5a37f722d14fa89fc6b18f1605b364fc11e23d8c27a"
+  }
+, { mapKey = "fgl-arbitrary"
+  , mapValue =
+      "b266f2d518328934d48c3b3b83176318ce114a8de777989f7ee011e7db75d6c1"
+  }
 , { mapKey = "filelock"
   , mapValue =
       "9d8780ad35f23d690065c103a7e56e6a52fb7ecd2b29a0d8216ab49438f9b255"
@@ -798,6 +806,10 @@
   , mapValue =
       "2742c54ea56afebc09ccdf653777c58eb73ee414b2e89a38db109ad23a553f0d"
   }
+, { mapKey = "graphviz"
+  , mapValue =
+      "41a9363d5009ef733abd368d6931b76609b987937d194e515c844167afe63e58"
+  }
 , { mapKey = "gridtables"
   , mapValue =
       "e94ffdc128fab5417b18e78b49864bf257c21210ab08ca25c9112ffed889282c"
@@ -1222,6 +1234,10 @@
   , mapValue =
       "5449de00863bcc19766e5b8eced6aeea801e42a344bc304c8a2d63589ac6aba2"
   }
+, { mapKey = "microbench"
+  , mapValue =
+      "093c19cf4508c9d9d77d88010651f3cc4ebd759e27a791e3f9aa5365a567fef7"
+  }
 , { mapKey = "microlens-aeson"
   , mapValue =
       "3eb5fe727b5fd851a6db5a0647d24e08b63cbd1d01e1622b7cdda349798678d0"
@@ -1570,6 +1586,10 @@
   , mapValue =
       "be52fe43924e1db7e02e9d9b953f7c9d0d865e2b7855616777b3526b5ffaf781"
   }
+, { mapKey = "quickcheck-state-machine"
+  , mapValue =
+      "8d8c8a52ca89f39118d2c20352475bd687af7f7e265d1056f736256636b0a383"
+  }
 , { mapKey = "quickcheck-text"
   , mapValue =
       "d73af28cadb1937150dbcb76a49d55091c3d084ed93e4a940fe28f0945d3a8e4"
@@ -2174,6 +2194,10 @@
   , mapValue =
       "447eebba10f034c83db4d9b12f5c7d0ddfbc9b26e1bfb0f67aa07b865cb25f89"
   }
+, { mapKey = "wl-pprint-text"
+  , mapValue =
+      "0822ed8e480c943204db1c04cbcea13047978f619562d9dbad0d437601fdd350"
+  }
 , { mapKey = "word-compat"
   , mapValue =
       "f63d25509feb22c99a724243f0569f5d78b4adcb04409a62522de5b270e08ed9"
diff --git a/overlay.nix b/overlay.nix
index 9bcab327341c93261e83d4b4f9a5998d55fc1d4a..158072f3832e85dafa0f1b1d3bbe24abe0afb464 100644
--- a/overlay.nix
+++ b/overlay.nix
@@ -295,6 +295,10 @@ final: prev: with pkgs.haskell.lib; {
 
   fcf-containers = final.callPackage (./pkgs/fcf-containers.nix) { };
 
+  fgl = final.callPackage (./pkgs/fgl.nix) { };
+
+  fgl-arbitrary = final.callPackage (./pkgs/fgl-arbitrary.nix) { };
+
   filelock = final.callPackage (./pkgs/filelock.nix) { };
 
   filemanip = final.callPackage (./pkgs/filemanip.nix) { };
@@ -401,6 +405,8 @@ final: prev: with pkgs.haskell.lib; {
 
   gitrev = final.callPackage (./pkgs/gitrev.nix) { };
 
+  graphviz = final.callPackage (./pkgs/graphviz.nix) { };
+
   gridtables = final.callPackage (./pkgs/gridtables.nix) { };
 
   groups = final.callPackage (./pkgs/groups.nix) { };
@@ -613,6 +619,8 @@ final: prev: with pkgs.haskell.lib; {
 
   mfsolve = final.callPackage (./pkgs/mfsolve.nix) { };
 
+  microbench = final.callPackage (./pkgs/microbench.nix) { };
+
   microlens-aeson = final.callPackage (./pkgs/microlens-aeson.nix) { };
 
   microlens-ghc = final.callPackage (./pkgs/microlens-ghc.nix) { };
@@ -787,6 +795,8 @@ final: prev: with pkgs.haskell.lib; {
 
   quickcheck-assertions = final.callPackage (./pkgs/quickcheck-assertions.nix) { };
 
+  quickcheck-state-machine = final.callPackage (./pkgs/quickcheck-state-machine.nix) { };
+
   quickcheck-text = final.callPackage (./pkgs/quickcheck-text.nix) { };
 
   quote-quot = final.callPackage (./pkgs/quote-quot.nix) { };
@@ -1089,6 +1099,8 @@ final: prev: with pkgs.haskell.lib; {
 
   wizards = final.callPackage (./pkgs/wizards.nix) { };
 
+  wl-pprint-text = final.callPackage (./pkgs/wl-pprint-text.nix) { };
+
   word-compat = final.callPackage (./pkgs/word-compat.nix) { };
 
   wreq = final.callPackage (./pkgs/wreq.nix) { };
diff --git a/pkgs/fgl-arbitrary.nix b/pkgs/fgl-arbitrary.nix
new file mode 100644
index 0000000000000000000000000000000000000000..1dc0acfbd5e65a99d4d85dbb82337159c6134b6f
--- /dev/null
+++ b/pkgs/fgl-arbitrary.nix
@@ -0,0 +1,21 @@
+{ mkDerivation, QuickCheck, base, containers, fgl, hspec, lib }:
+mkDerivation {
+  pname = "fgl-arbitrary";
+  version = "0.2.0.6";
+  sha256 = "6cf210a2ecbda21059647008cc8d85969308b21d18690f82d5f70d92435bd3d7";
+  isLibrary = true;
+  isExecutable = false;
+  enableSeparateDataOutput = false;
+  libraryHaskellDepends = [ base fgl QuickCheck ];
+  testHaskellDepends = [ base containers fgl hspec QuickCheck ];
+  enableLibraryProfiling = true;
+  enableExecutableProfiling = true;
+  doHaddock = true;
+  jailbreak = true;
+  doCheck = false;
+  doBenchmark = false;
+  hyperlinkSource = false;
+  description = "QuickCheck support for fgl";
+  license = lib.licenses.bsd3;
+  broken = false;
+}
\ No newline at end of file
diff --git a/pkgs/fgl.nix b/pkgs/fgl.nix
new file mode 100644
index 0000000000000000000000000000000000000000..0f1ec584b186fd04bd2d238c444aac784155236c
--- /dev/null
+++ b/pkgs/fgl.nix
@@ -0,0 +1,26 @@
+{ mkDerivation, QuickCheck, array, base, containers, deepseq, hspec
+, lib, microbench, transformers
+}:
+mkDerivation {
+  pname = "fgl";
+  version = "5.8.2.0";
+  sha256 = "44cf0cf720f1d3fb31689cab219adf9b1a5367b3fbf4bd6678f4d156f3e8c3b6";
+  isLibrary = true;
+  isExecutable = false;
+  enableSeparateDataOutput = false;
+  libraryHaskellDepends = [
+    array base containers deepseq transformers
+  ];
+  testHaskellDepends = [ base containers hspec QuickCheck ];
+  benchmarkHaskellDepends = [ base deepseq microbench ];
+  enableLibraryProfiling = true;
+  enableExecutableProfiling = true;
+  doHaddock = true;
+  jailbreak = true;
+  doCheck = false;
+  doBenchmark = false;
+  hyperlinkSource = false;
+  description = "Martin Erwig's Functional Graph Library";
+  license = lib.licenses.bsd3;
+  broken = false;
+}
\ No newline at end of file
diff --git a/pkgs/graphviz.nix b/pkgs/graphviz.nix
new file mode 100644
index 0000000000000000000000000000000000000000..6a0d95b510d4006e1d2fae4bb02387c1317866f0
--- /dev/null
+++ b/pkgs/graphviz.nix
@@ -0,0 +1,34 @@
+{ mkDerivation, QuickCheck, base, bytestring, colour, containers
+, criterion, deepseq, directory, dlist, fgl, fgl-arbitrary
+, filepath, graphviz, hspec, hspec-discover, lib, mtl, polyparse
+, process, temporary, text, wl-pprint-text
+}:
+mkDerivation {
+  pname = "graphviz";
+  version = "2999.20.2.0";
+  sha256 = "fcceeced6d716413566d9031716260a86b7fa0671f4727147318d507cb3270a2";
+  isLibrary = true;
+  isExecutable = true;
+  enableSeparateDataOutput = false;
+  libraryHaskellDepends = [
+    base bytestring colour containers directory dlist fgl filepath mtl
+    polyparse process temporary text wl-pprint-text
+  ];
+  testHaskellDepends = [
+    base containers fgl fgl-arbitrary filepath hspec QuickCheck text
+  ];
+  testSystemDepends = [ graphviz ];
+  testToolDepends = [ hspec-discover ];
+  benchmarkHaskellDepends = [ base criterion deepseq text ];
+  enableLibraryProfiling = true;
+  enableExecutableProfiling = true;
+  doHaddock = true;
+  jailbreak = true;
+  doCheck = false;
+  doBenchmark = false;
+  hyperlinkSource = false;
+  homepage = "https://gitlab.com/daniel-casanueva/haskell/graphviz";
+  description = "Bindings to Graphviz for graph visualisation";
+  license = lib.licenses.bsd3;
+  broken = false;
+}
\ No newline at end of file
diff --git a/pkgs/microbench.nix b/pkgs/microbench.nix
new file mode 100644
index 0000000000000000000000000000000000000000..15f230e2bebc7346bec5659fc01c2cd40e6c64cd
--- /dev/null
+++ b/pkgs/microbench.nix
@@ -0,0 +1,21 @@
+{ mkDerivation, base, lib, time }:
+mkDerivation {
+  pname = "microbench";
+  version = "0.1";
+  sha256 = "6fee3c592c9afb72bd7b5574872119464055b717491c612ffee7f57c8e85d717";
+  isLibrary = true;
+  isExecutable = false;
+  enableSeparateDataOutput = false;
+  libraryHaskellDepends = [ base time ];
+  enableLibraryProfiling = true;
+  enableExecutableProfiling = true;
+  doHaddock = true;
+  jailbreak = true;
+  doCheck = false;
+  doBenchmark = false;
+  hyperlinkSource = false;
+  homepage = "http://neugierig.org/software/darcs/browse/?r=microbench;a=summary";
+  description = "Microbenchmark Haskell code";
+  license = lib.licenses.bsd3;
+  broken = false;
+}
\ No newline at end of file
diff --git a/pkgs/quickcheck-state-machine.nix b/pkgs/quickcheck-state-machine.nix
new file mode 100644
index 0000000000000000000000000000000000000000..fb8c08cd9f884c721533ef7868d1daef51a100a7
--- /dev/null
+++ b/pkgs/quickcheck-state-machine.nix
@@ -0,0 +1,47 @@
+{ mkDerivation, MemoTrie, QuickCheck, aeson, ansi-wl-pprint, array
+, base, base-compat, bifunctors, bytestring, containers, directory
+, doctest, exceptions, filelock, filepath, generic-data
+, generics-sop, graphviz, hashable, hashtables, http-client, lib
+, monad-logger, mtl, network, persistent, persistent-postgresql
+, persistent-sqlite, persistent-template, postgresql-simple, pretty
+, pretty-show, process, quickcheck-instances, random, resource-pool
+, resourcet, servant, servant-client, servant-server, sop-core
+, split, stm, strict, string-conversions, tasty, tasty-hunit
+, tasty-quickcheck, text, time, unliftio, unliftio-core, vector
+, wai, warp
+}:
+mkDerivation {
+  pname = "quickcheck-state-machine";
+  version = "0.8.0";
+  sha256 = "426dc5279fdbe423d830fb21a10961345bb6f3000189e567db71c74558752eba";
+  isLibrary = true;
+  isExecutable = false;
+  enableSeparateDataOutput = false;
+  libraryHaskellDepends = [
+    ansi-wl-pprint base base-compat bytestring containers directory
+    exceptions filepath generic-data generics-sop graphviz MemoTrie mtl
+    pretty pretty-show process QuickCheck random sop-core split text
+    time unliftio vector
+  ];
+  testHaskellDepends = [
+    aeson array base bifunctors bytestring containers directory doctest
+    filelock filepath hashable hashtables http-client monad-logger mtl
+    network persistent persistent-postgresql persistent-sqlite
+    persistent-template postgresql-simple pretty-show process
+    QuickCheck quickcheck-instances random resource-pool resourcet
+    servant servant-client servant-server split stm strict
+    string-conversions tasty tasty-hunit tasty-quickcheck text unliftio
+    unliftio-core vector wai warp
+  ];
+  enableLibraryProfiling = true;
+  enableExecutableProfiling = true;
+  doHaddock = true;
+  jailbreak = true;
+  doCheck = false;
+  doBenchmark = false;
+  hyperlinkSource = false;
+  homepage = "https://github.com/stevana/quickcheck-state-machine#readme";
+  description = "Test monadic programs using state machine based models";
+  license = lib.licenses.bsd3;
+  broken = false;
+}
\ No newline at end of file
diff --git a/pkgs/wl-pprint-text.nix b/pkgs/wl-pprint-text.nix
new file mode 100644
index 0000000000000000000000000000000000000000..c47b3067edbaabb89f390aaee0b33ebcac79daed
--- /dev/null
+++ b/pkgs/wl-pprint-text.nix
@@ -0,0 +1,22 @@
+{ mkDerivation, base, base-compat, lib, text }:
+mkDerivation {
+  pname = "wl-pprint-text";
+  version = "1.2.0.2";
+  sha256 = "9215778d58ab9f71a4b8b5fb75c06438ff6ea7319a31eb6e97b4f67520dfb12b";
+  revision = "2";
+  editedCabalFile = "1zp64js72l8kkqn47hkl6rcangz14njfrhgdhq0w5x4nhvfi77md";
+  isLibrary = true;
+  isExecutable = false;
+  enableSeparateDataOutput = false;
+  libraryHaskellDepends = [ base base-compat text ];
+  enableLibraryProfiling = true;
+  enableExecutableProfiling = true;
+  doHaddock = true;
+  jailbreak = true;
+  doCheck = false;
+  doBenchmark = false;
+  hyperlinkSource = false;
+  description = "A Wadler/Leijen Pretty Printer for Text values";
+  license = lib.licenses.bsd3;
+  broken = false;
+}
\ No newline at end of file