diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -5,6 +5,16 @@
 ## Unreleased changes
 
 
+## Version 0.6.0.0
+
+-   **elynx-tree:** remove parallel folds with layers (`parBranchFoldMapWithLayer`
+    too special and slow).
+-   **elynx-tree:** fix various tree instances; add zip trees with appropriate
+    instances.
+-   Remove `monad-logger` dependency and implement lighter alternative.
+-   Significant changes to the tool chain.
+
+
 ## Version 0.5.1.0
 
 -   **elynx-tree:** new functions `isValidPath`, `isLeaf`, `depth`; add conversion
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 # The ELynx Suite
 
-Version: 0.5.1.0.
+Version: 0.6.0.0.
 Reproducible evolution made easy.
 
 <p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>
@@ -39,7 +39,7 @@
 
 # Installation
 
-ELynx is written in [Haskell](https://www.haskell.org/) and can be installed with [Stack](https://docs.haskellstack.org/en/stable/README/).
+ELynx is written in [Haskell](https://www.haskell.org/) and can be installed with [cabal-install](https://cabal.readthedocs.io/en/3.4/cabal-commands.html) or [Stack](https://docs.haskellstack.org/en/stable/README/).
 
 1.  Install Stack with your package manager, or directly from the web
     page.
@@ -67,15 +67,15 @@
     [PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable. Then, they can be used directly.
 
 
-# SLynx
+# Get help
 
-Handle evolutionary sequences.
+For example:
 
-    stack exec slynx -- --help | head -n -16
+    slynx --help
 
-    ELynx Suite version 0.5.1.0.
+    ELynx Suite version 0.6.0.0.
     Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
+    Compiled on September 3, 2021, at 20:56 pm, UTC.
     
     Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] 
                  [-f|--force] [--no-elynx-file] COMMAND
@@ -84,7 +84,7 @@
     Available options:
       -h,--help                Show this help text
       -V,--version             Show version
-      -v,--verbosity VALUE     Be verbose; one of: Quiet Warning Info Debug
+      -v,--verbosity VALUE     Be verbose; one of: Quiet Warn Info Debug
                                (default: Info)
       -o,--output-file-basename NAME
                                Specify base name of output file
@@ -112,107 +112,33 @@
       - Protein (amino acids)
       - ProteinX (amino acids; including gaps)
       - ProteinS (amino acids; including gaps, and translation stops)
-
-
-## Concatenate
-
-Concatenate multi sequence alignments.
-
-    stack exec slynx -- concatenate --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: slynx concatenate (-a|--alphabet NAME) INPUT-FILE
-      Concatenate sequences found in input files.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -a,--alphabet NAME       Specify alphabet type NAME
-      INPUT-FILE               Read sequences from INPUT-FILE
-      -h,--help                Show this help text
-
-
-## Examine
-
-Examine sequence with `slynx examine`.
-
-    stack exec slynx -- examine --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: slynx examine (-a|--alphabet NAME) INPUT-FILE [--per-site]
-      Examine sequences. If data is a multi sequence alignment, additionally analyze columns.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -a,--alphabet NAME       Specify alphabet type NAME
-      INPUT-FILE               Read sequences from INPUT-FILE
-      --per-site               Report per site summary statistics
-      -h,--help                Show this help text
-
-
-## Filter
-
-Filter sequences with `filer-rows`.
-
-    stack exec slynx -- filter-rows --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: slynx filter-rows (-a|--alphabet NAME) INPUT-FILE [--longer-than LENGTH] 
-                             [--shorter-than LENGTH] [--standard-characters]
-      Filter rows (or sequences) found in input files.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -a,--alphabet NAME       Specify alphabet type NAME
-      INPUT-FILE               Read sequences from INPUT-FILE
-      --longer-than LENGTH     Only keep sequences longer than LENGTH
-      --shorter-than LENGTH    Only keep sequences shorter than LENGTH
-      --standard-characters    Only keep sequences containing at least one standard
-                               (i.e., non-IUPAC) character
-      -h,--help                Show this help text
-
-Filter columns of multi sequence alignments with `filter-columns`.
-
-    stack exec slynx -- filter-columns --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
+      - ProteinI (amino acids; including gaps, translation stops, and IUPAC codes)
+    ELynx
+    -----
+    A Haskell library and tool set for computational biology. The goal of ELynx is
+    reproducible research. Evolutionary sequences and phylogenetic trees can be
+    read, viewed, modified and simulated. The command line with all arguments is
+    logged consistently, and automatically. Data integrity is verified using SHA256
+    sums so that validation of past analyses is possible without the need to
+    recompute the result.
     
-    Usage: slynx filter-columns (-a|--alphabet NAME) INPUT-FILE 
-                                [--standard-chars DOUBLE]
-      Filter columns of multi sequence alignments.
+    slynx     Analyze, modify, and simulate evolutionary sequences.
+    tlynx     Analyze, modify, and simulate phylogenetic trees.
+    elynx     Validate and redo past analyses.
     
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -a,--alphabet NAME       Specify alphabet type NAME
-      INPUT-FILE               Read sequences from INPUT-FILE
-      --standard-chars DOUBLE  Keep columns with a proportion standard (non-IUPAC)
-                               characters larger than DOUBLE in [0,1]
-      -h,--help                Show this help text
+    Get help for sub commands:
+      slynx examine --help
 
 
-## Simulate
+## Sub command
 
-Simulate sequences with `slynx simulate`.
+The documentation of sub commands can be accessed separately:
 
-    stack exec slynx -- simulate --help
+    slynx simulate --help
 
-    ELynx Suite version 0.5.1.0.
+    ELynx Suite version 0.6.0.0.
     Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
+    Compiled on September 3, 2021, at 20:56 pm, UTC.
     
     Usage: slynx simulate (-t|--tree-file Name) [-s|--substitution-model MODEL] 
                           [-m|--mixture-model MODEL] [-e|--edm-file NAME] 
@@ -281,315 +207,4 @@
          LG exchangeabilities with site profiles (Phylobayes) given in FILES.
          -m "EDM(LG-Custom)" -p FILES
     For special mixture models, mixture weights are optional.
-
-
-## Sub-sample
-
-Sub-sample columns from multi sequence alignments.
-
-    stack exec slynx -- sub-sample --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: slynx sub-sample (-a|--alphabet NAME) INPUT-FILE
-                            (-n|--number-of-sites INT)
-                            (-m|--number-of-alignments INT) [-S|--seed [INT]]
-      Sub-sample columns from multi sequence alignments.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -a,--alphabet NAME       Specify alphabet type NAME
-      INPUT-FILE               Read sequences from INPUT-FILE
-      -n,--number-of-sites INT Number of sites randomly drawn with replacement
-      -m,--number-of-alignments INT
-                               Number of multi sequence alignments to be created
-      -S,--seed [INT]          Seed for random number generator; list of 32 bit
-                               integers with up to 256 elements (default: random)
-      -h,--help                Show this help text
-    
-    Create a given number of multi sequence alignments, each of which contains a given number of random sites drawn from the original multi sequence alignment.
-
-
-## Translate
-
-Translate sequences.
-
-    stack exec slynx -- translate --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: slynx translate (-a|--alphabet NAME) INPUT-FILE (-r|--reading-frame INT)
-                           (-u|--universal-code CODE)
-      Translate from DNA to Protein or DNAX to ProteinX.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -a,--alphabet NAME       Specify alphabet type NAME
-      INPUT-FILE               Read sequences from INPUT-FILE
-      -r,--reading-frame INT   Reading frame [0|1|2].
-      -u,--universal-code CODE universal code; one of: Standard,
-                               VertebrateMitochondrial.
-      -h,--help                Show this help text
-
-
-# TLynx
-
-Handle phylogenetic trees in Newick format.
-
-    stack exec tlynx -- --help | head -n -16
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: tlynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME] 
-                 [-f|--force] [--no-elynx-file] COMMAND
-      Compare, examine, and simulate phylogenetic trees.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -v,--verbosity VALUE     Be verbose; one of: Quiet Warning Info Debug
-                               (default: Info)
-      -o,--output-file-basename NAME
-                               Specify base name of output file
-      -f,--force               Ignore previous analysis and overwrite existing
-                               output files.
-      --no-elynx-file          Do not write data required to reproduce an analysis.
-    
-    Available commands:
-      compare                  Compare two phylogenetic trees (compute distances and branch-wise differences).
-      connect                  Connect two phylogenetic trees in all ways (possibly honoring constraints).
-      distance                 Compute distances between many phylogenetic trees.
-      examine                  Compute summary statistics of phylogenetic trees.
-      shuffle                  Shuffle a phylogenetic tree (keep coalescent times, but shuffle topology and leaves).
-      simulate                 Simulate phylogenetic trees using a birth and death or coalescent process.
-    
-    
-    Available tree file formats:
-      - Newick Standard: Branch support values are stored in square brackets after branch lengths.
-      - Newick IqTree:   Branch support values are stored as node names after the closing bracket of forests.
-      - Newick RevBayes: Key-value pairs is provided in square brackets after node names as well as branch lengths. XXX: Key value pairs are ignored at the moment.
-
-
-## Compare
-
-Compute distances between phylogenetic trees.
-
-    stack exec tlynx -- compare --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: tlynx compare [-n|--normalize] [-b|--bipartitions] [-t|--intersect] 
-                         [-f|--newick-format FORMAT] NAMES
-      Compare two phylogenetic trees (compute distances and branch-wise differences).
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -n,--normalize           Normalize trees before comparison
-      -b,--bipartitions        Print and plot common and missing bipartitions
-      -t,--intersect           Compare intersections; i.e., before comparison, drop
-                               leaves that are not present in the other tree
-      -f,--newick-format FORMAT
-                               Newick tree format: Standard, IqTree, or RevBayes;
-                               default: Standard; for detailed help, see 'tlynx
-                               --help'
-      NAMES                    Tree files
-      -h,--help                Show this help text
-
-
-## Connect
-
-Connect two phylogenetic tree in all ways (possibly honoring constraints).
-
-    stack exec tlynx -- connect --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: tlynx connect [-f|--newick-format FORMAT] [-c|--contraints CONSTRAINTS]
-                         TREE-FILE-A TREE-FILE-B
-      Connect two phylogenetic trees in all ways (possibly honoring constraints).
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -f,--newick-format FORMAT
-                               Newick tree format: Standard, IqTree, or RevBayes;
-                               default: Standard; for detailed help, see 'tlynx
-                               --help'
-      -c,--contraints CONSTRAINTS
-                               File containing one or more Newick trees to be used
-                               as constraints
-      TREE-FILE-A              File containing the first Newick tree
-      TREE-FILE-B              File containing the second Newick tree
-      -h,--help                Show this help text
-
-
-## Distancce
-
-Compute distances between many phylogenetic trees.
-
-    stack exec tlynx -- distance --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: tlynx distance (-d|--distance MEASURE) [-n|--normalize] [-t|--intersect] 
-                          [-s|--summary-statistics] 
-                          [-m|--master-tree-file MASTER-TREE-File] 
-                          [-f|--newick-format FORMAT] [INPUT-FILES]
-      Compute distances between many phylogenetic trees.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -d,--distance MEASURE    Type of distance to calculate (available distance
-                               measures are listed below)
-      -n,--normalize           Normalize trees before distance calculation; only
-                               affect distances depending on branch lengths
-      -t,--intersect           Compare intersections; i.e., before comparison, drop
-                               leaves that are not present in the other tree
-      -s,--summary-statistics  Report summary statistics only
-      -m,--master-tree-file MASTER-TREE-File
-                               Compare all trees to the tree in the master tree
-                               file.
-      -f,--newick-format FORMAT
-                               Newick tree format: Standard, IqTree, or RevBayes;
-                               default: Standard; for detailed help, see 'tlynx
-                               --help'
-      INPUT-FILES              Read tree(s) from INPUT-FILES; if more files are
-                               given, one tree is expected per file
-      -h,--help                Show this help text
-    
-    Distance measures:
-      symmetric                Symmetric distance (Robinson-Foulds distance).
-      incompatible-split[VAL]  Incompatible split distance. Collapse branches with (normalized)
-                               support less than 0.0<=VAL<=1.0 before distance calculation;
-                               if, let's say, VAL>0.7, only well supported differences contribute
-                               to the total distance.
-      branch-score             Branch score distance.
-
-
-## Examine
-
-Compute summary statistics of phylogenetic trees.
-
-    stack exec tlynx -- examine --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: tlynx examine INPUT-FILE [-f|--newick-format FORMAT]
-      Compute summary statistics of phylogenetic trees.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      INPUT-FILE               Read trees from INPUT-FILE
-      -f,--newick-format FORMAT
-                               Newick tree format: Standard, IqTree, or RevBayes;
-                               default: Standard; for detailed help, see 'tlynx
-                               --help'
-      -h,--help                Show this help text
-
-
-## Shuffle
-
-Shuffle a phylogenetic tree (keep coalescent times, but shuffle topology and
-leaves).
-
-    stack exec tlynx -- shuffle --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: tlynx shuffle [-f|--newick-format FORMAT] [-n|--replicates N] TREE-FILE 
-                         [-S|--seed [INT]]
-      Shuffle a phylogenetic tree (keep coalescent times, but shuffle topology and leaves).
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -f,--newick-format FORMAT
-                               Newick tree format: Standard, IqTree, or RevBayes;
-                               default: Standard; for detailed help, see 'tlynx
-                               --help'
-      -n,--replicates N        Number of trees to generate
-      TREE-FILE                File containing a Newick tree
-      -S,--seed [INT]          Seed for random number generator; list of 32 bit
-                               integers with up to 256 elements (default: random)
-      -h,--help                Show this help text
-
-
-## Simulate
-
-Simulate phylogenetic trees using birth and death processes.
-
-    stack exec tlynx -- simulate --help
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: tlynx simulate (-t|--nTrees INT) (-n|--nLeaves INT) PROCESS 
-                          [-u|--sub-sample DOUBLE] [-s|--summary-statistics] 
-                          [-S|--seed [INT]]
-      Simulate phylogenetic trees using a birth and death or coalescent process.
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-      -t,--nTrees INT          Number of trees
-      -n,--nLeaves INT         Number of leaves per tree
-      -u,--sub-sample DOUBLE   Perform sub-sampling; see below.
-      -s,--summary-statistics  For each branch, print length and number of children
-      -S,--seed [INT]          Seed for random number generator; list of 32 bit
-                               integers with up to 256 elements (default: random)
-      -h,--help                Show this help text
-    
-    Available processes:
-      birthdeath               Birth and death process
-      coalescent               Coalescent process
-    
-    See, for example, 'tlynx simulate birthdeath --help'.
-    Sub-sample with probability p:
-      1. Simulate one big tree with n'=round(n/p), n'>=n, leaves;
-      2. Randomly sample sub-trees with n leaves.
-      (With p=1.0, the same tree is reported over and over again.)
-
-
-# ELynx
-
-Validate and (optionally) redo past ELynx analyses.
-
-    stack exec elynx -- --help | head -n -16
-
-    ELynx Suite version 0.5.1.0.
-    Developed by Dominik Schrempf.
-    Compiled on June 12, 2021, at 14:54 pm, UTC.
-    
-    Usage: elynx COMMAND
-      Validate and redo past ELynx analyses
-    
-    Available options:
-      -h,--help                Show this help text
-      -V,--version             Show version
-    
-    Available commands:
-      validate                 Validate an ELynx analysis
-      redo                     Redo an ELynx analysis
 
diff --git a/src/TLynx/Compare/Compare.hs b/src/TLynx/Compare/Compare.hs
--- a/src/TLynx/Compare/Compare.hs
+++ b/src/TLynx/Compare/Compare.hs
@@ -19,21 +19,14 @@
 
 import Control.Monad
 import Control.Monad.IO.Class
-import Control.Monad.Logger
 import Control.Monad.Trans.Reader (ask)
 import qualified Data.ByteString.Lazy.Char8 as BL
 import Data.List (intercalate)
 import qualified Data.Map as M
 import qualified Data.Set as S
 import qualified Data.Text as T
-import qualified Data.Text.Encoding as E
 import qualified Data.Text.IO as T
 import ELynx.Tools
-  ( Arguments (..),
-    ELynx,
-    GlobalArguments (..),
-    outHandle,
-  )
 import ELynx.Tree
 import Graphics.Gnuplot.Simple
 import System.IO
@@ -47,8 +40,8 @@
     CompareArguments
     (Tree Phylo Name, Tree Phylo Name)
 treesOneFile tf = do
-  nwF <- argsNewickFormat . local <$> ask
-  $(logInfo) $ T.pack $ "Parse file '" ++ tf ++ "'."
+  nwF <- argsNewickFormat . localArguments <$> ask
+  logInfoS $ "Parse file '" ++ tf ++ "'."
   ts <- liftIO $ parseTrees nwF tf
   let n = length ts
   case compare n 2 of
@@ -64,25 +57,25 @@
     CompareArguments
     (Tree Phylo Name, Tree Phylo Name)
 treesTwoFiles tf1 tf2 = do
-  nwF <- argsNewickFormat . local <$> ask
-  $(logInfo) $ T.pack $ "Parse first tree file '" ++ tf1 ++ "'."
+  nwF <- argsNewickFormat . localArguments <$> ask
+  logInfoS $ "Parse first tree file '" ++ tf1 ++ "'."
   t1 <- liftIO $ parseTree nwF tf1
-  $(logInfo) $ T.pack $ "Parse second tree file '" ++ tf2 ++ "'."
+  logInfoS $ "Parse second tree file '" ++ tf2 ++ "'."
   t2 <- liftIO $ parseTree nwF tf2
   return (t1, t2)
 
 -- | More detailed comparison of two trees.
 compareCmd :: ELynx CompareArguments ()
 compareCmd = do
-  l <- local <$> ask
+  l <- localArguments <$> ask
   -- Determine output handle (stdout or file).
   outH <- outHandle "results" ".out"
   -- Read input.
-  let inFiles = argsInFiles l
-      nFiles = length inFiles
-  (tr1, tr2) <- case nFiles of
-    1 -> treesOneFile (head inFiles)
-    2 -> treesTwoFiles (head inFiles) (head . tail $ inFiles)
+  let inFs = argsInFiles l
+      nFs = length inFs
+  (tr1, tr2) <- case nFs of
+    1 -> treesOneFile (head inFs)
+    2 -> treesTwoFiles (head inFs) (head . tail $ inFs)
     _ ->
       error
         "Need two input files with one tree each or one input file with two trees."
@@ -122,7 +115,7 @@
       formatD
         "Symmetric"
         (T.pack $ show $ symmetric t1 t2)
-  case (phyloToLengthTree t1, phyloToLengthTree t2) of
+  case (toLengthTree t1, toLengthTree t2) of
     (Right t1', Right t2') -> do
       liftIO $
         T.hPutStrLn outH $
@@ -130,15 +123,15 @@
             "Branch score"
             (T.pack $ show $ branchScore t1' t2')
     _ -> do
-      $(logInfo) "Some branches do not have length values."
-      $(logInfo) "Distances involving length cannot be calculated."
+      logInfoS "Some branches do not have length values."
+      logInfoS "Distances involving length cannot be calculated."
   case (toExplicitTree t1, toExplicitTree t2) of
     (Right t1', Right t2') -> do
       let t1n = normalizeBranchSupport t1'
           t2n = normalizeBranchSupport t2'
-      $(logDebug) "Trees with normalized branch support values:"
-      $(logDebug) $ E.decodeUtf8 $ BL.toStrict $ toNewick $ toPhyloTree t1n
-      $(logDebug) $ E.decodeUtf8 $ BL.toStrict $ toNewick $ toPhyloTree t2n
+      logDebugS "Trees with normalized branch support values:"
+      logDebugB $ toNewick $ toPhyloTree t1n
+      logDebugB $ toNewick $ toPhyloTree t2n
       liftIO $
         T.hPutStrLn outH $
           formatD
@@ -172,8 +165,8 @@
     --   (T.pack $ show $ incompatibleSplits (collapse 1.01 t1n) (collapse 1.01 t2n))
     -- liftIO $ BL.hPutStrLn outH $ toNewick (collapse 1.01 t1n)
     _ -> do
-      $(logInfo) "Some branches do not have support values."
-      $(logInfo) "Distances involving branch support cannot be calculated."
+      logInfoS "Some branches do not have support values."
+      logInfoS "Distances involving branch support cannot be calculated."
 
 analyzeBipartitions ::
   Handle ->
@@ -181,7 +174,7 @@
   Tree Phylo Name ->
   ELynx CompareArguments ()
 analyzeBipartitions outH t1 t2 =
-  case (phyloToLengthTree t1, phyloToLengthTree t2) of
+  case (toLengthTree t1, toLengthTree t2) of
     (Right t1l, Right t2l) -> do
       let bp1 = either error id $ bipartitions t1l
           bp2 = either error id $ bipartitions t2l
@@ -214,8 +207,8 @@
           liftIO $ hPutStrLn outH "There are no common bipartitions."
           liftIO $ hPutStrLn outH "No plots have been generated."
         else do
-          let bpToBrLen1 = M.map (fromLength . getLen) $ either error id $ bipartitionToBranch t1l
-              bpToBrLen2 = M.map (fromLength . getLen) $ either error id $ bipartitionToBranch t2l
+          let bpToBrLen1 = M.map (fromLength . getLength) $ either error id $ bipartitionToBranch t1l
+              bpToBrLen2 = M.map (fromLength . getLength) $ either error id $ bipartitionToBranch t2l
           liftIO $
             hPutStrLn
               outH
@@ -230,19 +223,19 @@
             )
           -- XXX: This circumvents the extension checking, and hash creation for
           -- elynx files.
-          bn <- outFileBaseName . global <$> ask
+          bn <- outFileBaseName . globalArguments <$> ask
           case bn of
             Nothing ->
-              $(logInfo) "No output file name provided. Do not generate plots."
+              logInfoS "No output file name provided. Do not generate plots."
             Just fn -> do
               let compareCommonBps =
                     [ (bpToBrLen1 M.! b, bpToBrLen2 M.! b)
                       | b <- S.toList bpCommon
                     ]
               liftIO $ epspdfPlot fn (plotBps compareCommonBps)
-              $(logInfo)
+              logInfoS
                 "Comparison of branch lengths plot generated (EPS and PDF)"
-    _ -> $(logWarn) "Not all branches have a length! Can not analyze bipartitions."
+    _ -> logWarnS "Not all branches have a length! Can not analyze bipartitions."
 
 header :: String
 header = intercalate "  " $ cols ++ ["Bipartition"]
diff --git a/src/TLynx/Connect/Connect.hs b/src/TLynx/Connect/Connect.hs
--- a/src/TLynx/Connect/Connect.hs
+++ b/src/TLynx/Connect/Connect.hs
@@ -18,17 +18,11 @@
 where
 
 import Control.Monad.IO.Class
-import Control.Monad.Logger
 import Control.Monad.Trans.Reader (ask)
 import qualified Data.ByteString.Lazy.Char8 as BL
+import Data.Default.Class
 import qualified Data.Set as S
 import ELynx.Tools
-  ( Arguments (..),
-    ELynx,
-    fromBs,
-    outHandle,
-    tShow,
-  )
 import ELynx.Tree
 import System.IO
 import TLynx.Connect.Options
@@ -43,7 +37,13 @@
 -- introduced.
 --
 -- Return 'Left' if one tree has a non-bifurcating root node.
-connect :: (Semigroup e, Splittable e) => e -> a -> Tree e a -> Tree e a -> Either String (Forest e a)
+connect ::
+  (Semigroup e, Splittable e, Default a) =>
+  e ->
+  a ->
+  Tree e a ->
+  Tree e a ->
+  Either String (Forest e a)
 connect br lb l r = do
   ls <- roots l
   rs <- roots r
@@ -55,7 +55,7 @@
 -- nodes, respectively, there are (n-2)*(m-2) ways to connect them.
 connectCmd :: ELynx ConnectArguments ()
 connectCmd = do
-  lArgs <- local <$> ask
+  lArgs <- localArguments <$> ask
   outH <- outHandle "results" ".out"
   -- Do we have constraints or not?
   let cs = constraints lArgs
@@ -104,34 +104,34 @@
     ConnectArguments
     (Tree Length Name, Tree Length Name)
 parseTreeTuple l r = do
-  nwF <- nwFormat . local <$> ask
+  nwF <- nwFormat . localArguments <$> ask
   tl <- liftIO $ parseTree nwF l
   tr <- liftIO $ parseTree nwF r
-  $(logInfo) "Tree 1:"
-  $(logInfo) $ fromBs $ toNewick tl
-  $(logInfo) "Tree 2:"
-  $(logInfo) $ fromBs $ toNewick tr
-  return (either error id $ phyloToLengthTree tl, either error id $ phyloToLengthTree tr)
+  logInfoS "Tree 1:"
+  logInfoB $ toNewick tl
+  logInfoS "Tree 2:"
+  logInfoB $ toNewick tr
+  return (either error id $ toLengthTree tl, either error id $ toLengthTree tr)
 
 connectOnly :: Handle -> FilePath -> FilePath -> ELynx ConnectArguments ()
 connectOnly h l r = do
   (tl, tr) <- parseTreeTuple l r
   let ts = connectTrees tl tr
-  $(logInfo) $ "Connected trees: " <> tShow (length ts)
-  liftIO $ BL.hPutStr h $ BL.unlines $ map (toNewick . measurableToPhyloTree) ts
+  logInfoS $ "Connected trees: " <> show (length ts)
+  liftIO $ BL.hPutStr h $ BL.unlines $ map (toNewick . lengthToPhyloTree) ts
 
 connectAndFilter ::
   Handle -> FilePath -> FilePath -> FilePath -> ELynx ConnectArguments ()
 connectAndFilter h c l r = do
-  nwF <- nwFormat . local <$> ask
+  nwF <- nwFormat . localArguments <$> ask
   cts <- liftIO $ parseTrees nwF c
-  $(logInfo) "Constraints:"
-  $(logInfo) $ fromBs $ BL.intercalate "\n" $ map toNewick cts
+  logInfoS "Constraints:"
+  logInfoB $ BL.intercalate "\n" $ map toNewick cts
   (tl, tr) <- parseTreeTuple l r
   let ts = connectTrees tl tr
       cs = map S.fromList $ concatMap multifurcatingGroups cts :: [Constraint Name]
       -- Only collect trees that are compatible with the constraints.
       ts' = filter (compatibleWith getName cs) ts
-  $(logInfo) $ "Connected  trees: " <> tShow (length ts)
-  $(logInfo) $ "Compatible trees: " <> tShow (length ts')
-  liftIO $ BL.hPutStr h $ BL.unlines $ map (toNewick . measurableToPhyloTree) ts'
+  logInfoS $ "Connected  trees: " <> show (length ts)
+  logInfoS $ "Compatible trees: " <> show (length ts')
+  liftIO $ BL.hPutStr h $ BL.unlines $ map (toNewick . lengthToPhyloTree) ts'
diff --git a/src/TLynx/Distance/Distance.hs b/src/TLynx/Distance/Distance.hs
--- a/src/TLynx/Distance/Distance.hs
+++ b/src/TLynx/Distance/Distance.hs
@@ -24,10 +24,6 @@
     when,
   )
 import Control.Monad.IO.Class
-import Control.Monad.Logger
-  ( logDebug,
-    logInfo,
-  )
 import Control.Monad.Trans.Class
 import Control.Monad.Trans.Reader hiding (local)
 import Data.Bifunctor
@@ -36,8 +32,6 @@
 import Data.Maybe
 import qualified Data.Text as T
 import qualified Data.Text.IO as T
-import qualified Data.Text.Lazy as LT
-import qualified Data.Text.Lazy.Encoding as LT
 import qualified Data.Vector.Unboxed as V
 import ELynx.Tools
 import ELynx.Tree
@@ -87,7 +81,7 @@
 -- | Compute distance functions between phylogenetic trees.
 distance :: ELynx DistanceArguments ()
 distance = do
-  l <- local <$> ask
+  l <- localArguments <$> ask
   let nwFormat = argsNewickFormat l
   -- Determine output handle (stdout or file).
   outH <- outHandle "results" ".out"
@@ -96,44 +90,43 @@
   mtree <- case mname of
     Nothing -> return Nothing
     Just f -> do
-      $(logInfo) $ T.pack $ "Read master tree from file: " <> f <> "."
+      logInfoS $ "Read master tree from file: " <> f <> "."
       t <- liftIO $ parseTree nwFormat f
-      $(logInfo) "Compute distances between all trees and master tree."
+      logInfoS "Compute distances between all trees and master tree."
       return $ Just t
   let tfps = argsInFiles l
   (trees, names) <- case tfps of
     [] -> error "No tree input files given."
     [tf] -> do
-      $(logInfo) "Read trees from single file."
+      logInfoS "Read trees from single file."
       ts <- liftIO $ parseTrees nwFormat tf
-      $(logInfo) $ tShow (length ts) <> " trees found in file."
-      $(logInfo) "Trees are indexed with integers."
+      logInfoS $ show (length ts) <> " trees found in file."
+      logInfoS "Trees are indexed with integers."
       return (ts, map show [0 .. length ts - 1])
     _ -> do
-      $(logInfo) "Read trees from files."
+      logInfoS "Read trees from files."
       ts <- liftIO $ mapM (parseTree nwFormat) tfps
-      $(logInfo) "Trees are named according to their file names."
+      logInfoS "Trees are named according to their file names."
       return (ts, tfps)
   when (null trees) (error "Not enough trees found in files.")
   when
     (isNothing mtree && length trees == 1)
     (error "Not enough trees found in files.")
-  -- when (isNothing mtree) $ $(logInfo)
+  -- when (isNothing mtree) $ logInfoS
   --   "Compute pairwise distances between trees from different files."
-  $(logDebug) "The trees are:"
-  $(logDebug) $ LT.toStrict $ LT.decodeUtf8 $ BL.unlines $ map toNewick trees
+  logDebugS "The trees are:"
+  logDebugB $ BL.unlines $ map toNewick trees
   -- Set the distance measure.
   let dist = argsDistance l
   case argsDistance l of
-    Symmetric -> $(logInfo) "Use symmetric (Robinson-Foulds) distance."
+    Symmetric -> logInfoS "Use symmetric (Robinson-Foulds) distance."
     IncompatibleSplit val -> do
-      $(logInfo) "Use incompatible split distance."
-      $(logInfo) $
-        T.pack $
-          "Collapse nodes with support less than "
-            ++ show val
-            ++ "."
-    BranchScore -> $(logInfo) "Use branch score distance."
+      logInfoS "Use incompatible split distance."
+      logInfoS $
+        "Collapse nodes with support less than "
+          ++ show val
+          ++ "."
+    BranchScore -> logInfoS "Use branch score distance."
   let distanceMeasure' ::
         Tree Phylo Name ->
         Tree Phylo Name ->
@@ -143,15 +136,17 @@
         IncompatibleSplit val ->
           second fromIntegral $
             incompatibleSplits
-              (collapse val $ normalizeBranchSupport $ either error id $ phyloToSupportTree t1)
-              (collapse val $ normalizeBranchSupport $ either error id $ phyloToSupportTree t2)
+              (collapse val $ normalizeBranchSupport $ either error id $ toSupportTree t1)
+              (collapse val $ normalizeBranchSupport $ either error id $ toSupportTree t2)
         BranchScore ->
-          branchScore (normalizeF $ either error id $ phyloToLengthTree t1) (normalizeF $ either error id $ phyloToLengthTree t2)
+          branchScore
+            (normalizeF $ either error id $ toLengthTree t1)
+            (normalizeF $ either error id $ toLengthTree t2)
         where
           normalizeF = if argsNormalize l then normalizeBranchLengths else id
   -- Possibly intersect trees before distance calculation.
   when (argsIntersect l) $
-    $(logInfo) "Intersect trees before calculation of distances."
+    logInfoS "Intersect trees before calculation of distances."
   let distanceMeasure =
         if argsIntersect l
           then
@@ -162,12 +157,13 @@
           else distanceMeasure'
   -- Possibly normalize trees.
   when (argsNormalize l) $
-    $(logInfo) "Normalize trees before calculation of distances."
+    logInfoS "Normalize trees before calculation of distances."
   let dsTriplets = case mtree of
         Nothing -> pairwise distanceMeasure trees
         Just masterTree -> [(0, i, distanceMeasure masterTree t') | (i, t') <- zip [1 ..] trees]
       ds = map (\(_, _, x) -> x) dsTriplets
       dsVec = V.fromList ds
+  -- TODO: This should never happen (hPutStrLn??).
   liftIO $
     hPutStrLn outH $
       "Summary statistics of "
@@ -192,24 +188,23 @@
   -- BS.putStrLn $ BS.unlines $ map toNewick tsN
   -- BS.putStrLn $ BS.unlines $ map toNewick tsC
 
-  lift $
-    unless
-      (argsSummaryStatistics l)
-      ( do
-          let n = maximum $ 6 : map length names
-              m = length $ show dist
-          lift $ hPutStrLn outH ""
-          lift $ BL.hPutStrLn outH $ header n m dist
-          case mname of
-            Nothing ->
-              lift $
-                BL.hPutStr outH $
-                  BL.unlines
-                    (map (showTriplet n m names) dsTriplets)
-            Just mn ->
-              lift $
-                BL.hPutStr outH $
-                  BL.unlines
-                    (map (showTriplet n m (mn : names)) dsTriplets)
-      )
+  unless
+    (argsSummaryStatistics l)
+    ( do
+        let n = maximum $ 6 : map length names
+            m = length $ show dist
+        lift $ hPutStrLn outH ""
+        lift $ BL.hPutStrLn outH $ header n m dist
+        case mname of
+          Nothing ->
+            lift $
+              BL.hPutStr outH $
+                BL.unlines
+                  (map (showTriplet n m names) dsTriplets)
+          Just mn ->
+            lift $
+              BL.hPutStr outH $
+                BL.unlines
+                  (map (showTriplet n m (mn : names)) dsTriplets)
+    )
   liftIO $ hClose outH
diff --git a/src/TLynx/Examine/Examine.hs b/src/TLynx/Examine/Examine.hs
--- a/src/TLynx/Examine/Examine.hs
+++ b/src/TLynx/Examine/Examine.hs
@@ -18,12 +18,10 @@
 
 import Control.Monad (unless)
 import Control.Monad.IO.Class
-import Control.Monad.Logger
 import Control.Monad.Trans.Reader (ask)
 import qualified Data.ByteString.Lazy.Char8 as BL
 import Data.Containers.ListUtils (nubOrd)
 import Data.List ((\\))
-import qualified Data.Text as T
 import ELynx.Tools
 import ELynx.Tree
 import System.IO
@@ -60,14 +58,14 @@
 
 readTrees :: FilePath -> ELynx ExamineArguments (Forest Phylo Name)
 readTrees fp = do
-  $(logInfo) $ T.pack $ "Read tree(s) from file " <> fp <> "."
-  nf <- argsNewickFormat . local <$> ask
+  logInfoS $ "Read tree(s) from file " <> fp <> "."
+  nf <- argsNewickFormat . localArguments <$> ask
   liftIO $ parseTrees nf fp
 
 examineTree :: HasName a => Handle -> Tree Phylo a -> IO ()
 examineTree h t = do
   hPutStrLn h $ "Number of leaves: " ++ show (length lvs)
-  let l = phyloToLengthTree t
+  let l = toLengthTree t
   case l of
     Left _ -> hPutStrLn h "Branch lengths not available."
     Right t' -> BL.hPutStrLn h $ summarizeLengths t'
@@ -82,7 +80,7 @@
 -- | Examine phylogenetic trees.
 examine :: ELynx ExamineArguments ()
 examine = do
-  l <- local <$> ask
+  l <- localArguments <$> ask
   let inFn = argsInFile l
   trs <- readTrees inFn
   outH <- outHandle "results" ".out"
diff --git a/src/TLynx/Shuffle/Options.hs b/src/TLynx/Shuffle/Options.hs
--- a/src/TLynx/Shuffle/Options.hs
+++ b/src/TLynx/Shuffle/Options.hs
@@ -26,7 +26,7 @@
   { nwFormat :: NewickFormat,
     nReplicates :: Int,
     inFile :: FilePath,
-    argsSeed :: Seed
+    argsSeed :: SeedOpt
   }
   deriving (Eq, Show, Generic)
 
@@ -34,7 +34,7 @@
   inFiles = pure . inFile
   outSuffixes _ = [".tree"]
   getSeed = Just . argsSeed
-  setSeed a s = a {argsSeed = Fixed s}
+  setSeed a s = a {argsSeed = s}
   parser = shuffleArguments
   cmdName = "shuffle"
   cmdDsc =
diff --git a/src/TLynx/Shuffle/Shuffle.hs b/src/TLynx/Shuffle/Shuffle.hs
--- a/src/TLynx/Shuffle/Shuffle.hs
+++ b/src/TLynx/Shuffle/Shuffle.hs
@@ -23,7 +23,6 @@
 import qualified Control.Comonad as C
 import Control.Monad (when)
 import Control.Monad.IO.Class (liftIO)
-import Control.Monad.Logger (logDebug, logInfo)
 import Control.Monad.Trans.Reader (ask)
 import qualified Data.ByteString.Lazy.Char8 as BL
 import ELynx.Tools
@@ -34,8 +33,8 @@
   )
 import System.IO (hClose)
 import System.Random.MWC (GenIO, initialize)
-import TLynx.Shuffle.Options
 import TLynx.Parsers
+import TLynx.Shuffle.Options
 
 -- | Shuffle a tree. Get all coalescent times, shuffle them. Get all leaves,
 -- shuffle them. Connect the shuffled leaves with the shuffled coalescent times.
@@ -43,32 +42,34 @@
 -- times and leaves.
 shuffleCmd :: ELynx ShuffleArguments ()
 shuffleCmd = do
-  l <- local <$> ask
+  l <- localArguments <$> ask
   h <- outHandle "results" ".tree"
   let nwF = nwFormat l
   tPhylo <- liftIO $ parseTree nwF (inFile l)
-  $(logInfo) "Input tree:"
-  $(logInfo) $ fromBs $ toNewick tPhylo
-  let t = either error id $ phyloToLengthTree tPhylo
+  logInfoS "Input tree:"
+  logInfoB $ toNewick tPhylo
+  let t = either error id $ toLengthTree tPhylo
   -- Check if tree is ultrametric enough.
   let dh = sum $ map (height t -) (distancesOriginLeaves t)
-  $(logDebug) $ "Distance in branch length to being ultrametric: " <> tShow dh
+  logDebugS $ "Distance in branch length to being ultrametric: " <> show dh
   when (dh > 2e-4) (error "Tree is not ultrametric.")
   when (dh > toLengthUnsafe eps && dh < 2e-4) $
-    $(logInfo)
+    logInfoS
       "Tree is nearly ultrametric, ignore branch length differences smaller than 2e-4."
-  when (dh < toLengthUnsafe eps) $ $(logInfo) "Tree is ultrametric."
+  when (dh < toLengthUnsafe eps) $ logInfoS "Tree is ultrametric."
   let cs = filter (> 0) $ labels $ C.extend rootHeight t
       ls = map getName $ leaves t
-  $(logDebug) $ "Number of coalescent times: " <> tShow (length cs)
-  $(logDebug) $ "Number of leaves: " <> tShow (length ls)
-  $(logDebug) "The coalescent times are: "
-  $(logDebug) $ tShow cs
-  gen <- case argsSeed l of
-    Random -> error "Seed not available; please contact maintainer."
-    Fixed s -> liftIO $ initialize s
+  logDebugS $ "Number of coalescent times: " <> show (length cs)
+  logDebugS $ "Number of leaves: " <> show (length ls)
+  logDebugS "The coalescent times are: "
+  logDebugS $ show cs
+  gen <- liftIO $
+    initialize $ case argsSeed l of
+      RandomUnset -> error "Seed not available; please contact maintainer."
+      RandomSet s -> s
+      Fixed s -> s
   ts <- liftIO $ shuffleT (nReplicates l) (height t) cs ls gen
-  liftIO $ BL.hPutStr h $ BL.unlines $ map (toNewick . measurableToPhyloTree) ts
+  liftIO $ BL.hPutStr h $ BL.unlines $ map (toNewick . lengthToPhyloTree) ts
   liftIO $ hClose h
 
 shuffleT ::
diff --git a/src/TLynx/Simulate/Options.hs b/src/TLynx/Simulate/Options.hs
--- a/src/TLynx/Simulate/Options.hs
+++ b/src/TLynx/Simulate/Options.hs
@@ -24,7 +24,7 @@
 
 import Data.List
 import Data.Maybe
-import ELynx.Tools hiding (Random)
+import ELynx.Tools
 import ELynx.Tree.Simulate.PointProcess (TimeSpec (..))
 import Options.Applicative
 
@@ -85,7 +85,7 @@
     -- | Only print summary statistics?
     argsSumStat :: Bool,
     -- | Seed of NRG, random if 'Nothing'.
-    argsSeed :: Seed
+    argsSeed :: SeedOpt
   }
   deriving (Eq, Show, Generic)
 
@@ -93,7 +93,7 @@
   inFiles _ = []
   outSuffixes _ = [".tree"]
   getSeed = Just . argsSeed
-  setSeed a s = a {argsSeed = Fixed s}
+  setSeed a s = a {argsSeed = s}
   parser = simulateArguments
   cmdName = "simulate"
   cmdDsc = ["Simulate phylogenetic trees using a birth and death or coalescent process."]
@@ -243,5 +243,5 @@
 simulateFooter :: [String]
 simulateFooter =
   [ "See, for example, 'tlynx simulate birthdeath --help'.",
-    "Sub-sample with probability p:\n  1. Simulate one big tree with n'=round(n/p), n'>=n, leaves;\n  2. Randomly sample sub-trees with n leaves.\n  (With p=1.0, the same tree is reported over and over again.)"
+    "Sub-sample with probability p:\n  1. Simulate one big tree with n'=round(n/p), n'>=n, leaves;\n  2. Randomly sample sub trees with n leaves.\n  (With p=1.0, the same tree is reported over and over again.)"
   ]
diff --git a/src/TLynx/Simulate/Simulate.hs b/src/TLynx/Simulate/Simulate.hs
--- a/src/TLynx/Simulate/Simulate.hs
+++ b/src/TLynx/Simulate/Simulate.hs
@@ -26,12 +26,11 @@
 where
 
 import Control.Concurrent (getNumCapabilities)
-import Control.Concurrent.Async.Lifted.Safe
+import Control.Concurrent.Async
   ( mapConcurrently,
   )
 import Control.Monad
 import Control.Monad.IO.Class
-import Control.Monad.Logger
 import Control.Monad.Trans.Reader hiding (local)
 import Control.Parallel.Strategies
 import qualified Data.ByteString.Builder as BB
@@ -40,9 +39,6 @@
 import Data.Maybe
 import qualified Data.Sequence as Seq
 import qualified Data.Set as Set
-import qualified Data.Text as T
-import qualified Data.Text.Lazy as LT
-import qualified Data.Text.Lazy.Encoding as LT
 import ELynx.Tools
 import ELynx.Tree
 import qualified ELynx.Tree.Simulate.Coalescent as CS
@@ -53,12 +49,12 @@
 -- | Simulate phylogenetic trees using birth and death process.
 simulate :: ELynx SimulateArguments ()
 simulate = do
-  l@(SimulateArguments nTrees nLeaves pr subS sumS (Fixed s)) <- local <$> ask
+  l@(SimulateArguments nTrees nLeaves pr subS sumS (Fixed s)) <- localArguments <$> ask
   c <- liftIO getNumCapabilities
-  logNewSection "Arguments"
-  $(logInfo) $ T.pack $ reportSimulateArguments l
-  logNewSection "Simulation"
-  $(logInfo) $ T.pack $ "Number of used cores: " <> show c
+  logInfoNewSection "Arguments"
+  logInfoS $ reportSimulateArguments l
+  logInfoNewSection "Simulation"
+  logInfoS $ "Number of used cores: " <> show c
   gs <- liftIO $ initialize s >>= \gen -> splitGen c gen
   let chunks = getChunks c nTrees
   trs <- case pr of
@@ -82,7 +78,7 @@
   let ls =
         if sumS
           then parMap rpar (formatNChildSumStat . toNChildSumStat) trs
-          else parMap rpar toNewick $ map measurableToPhyloTree trs
+          else parMap rpar toNewick $ map lengthToPhyloTree trs
   let res = BL.unlines ls
   out "simulated trees" res ".tree"
 
@@ -130,21 +126,19 @@
   let nLeavesBigTree = (round $ fromIntegral nLeaves / p) :: Int
       l' = l * r
       m' = m - l * (1.0 - r)
-  logNewSection $
-    T.pack $
-      "Simulate one big tree with "
-        <> show nLeavesBigTree
-        <> " leaves."
+  logInfoNewSection $
+    "Simulate one big tree with "
+      <> show nLeavesBigTree
+      <> " leaves."
   tr <- liftIO $ PP.simulateReconstructedTree nLeavesBigTree timeSpec l' m' (head gs)
   -- Log the base tree.
-  $(logInfo) $ LT.toStrict $ LT.decodeUtf8 $ toNewick $ measurableToPhyloTree tr
-  logNewSection $
-    T.pack $
-      "Sub sample "
-        <> show (sum chunks)
-        <> " trees with "
-        <> show nLeaves
-        <> " leaves."
+  logInfoB $ toNewick $ lengthToPhyloTree tr
+  logInfoNewSection $
+    "Sub sample "
+      <> show (sum chunks)
+      <> " trees with "
+      <> show nLeaves
+      <> " leaves."
   let lvs = Seq.fromList $ leaves tr
   trss <-
     liftIO $
@@ -162,21 +156,19 @@
   ELynx SimulateArguments (Forest Length Int)
 coalSimulateAndSubSampleNTreesConcurrently nL p chunks gs = do
   let nLeavesBigTree = (round $ fromIntegral nL / p) :: Int
-  logNewSection $
-    T.pack $
-      "Simulate one big tree with "
-        <> show nLeavesBigTree
-        <> " leaves."
+  logInfoNewSection $
+    "Simulate one big tree with "
+      <> show nLeavesBigTree
+      <> " leaves."
   tr <- liftIO $ CS.simulate nLeavesBigTree (head gs)
   -- Log the base tree.
-  $(logInfo) $ LT.toStrict $ LT.decodeUtf8 $ toNewick $ measurableToPhyloTree tr
-  logNewSection $
-    T.pack $
-      "Sub sample "
-        <> show (sum chunks)
-        <> " trees with "
-        <> show nL
-        <> " leaves."
+  logInfoB $ toNewick $ lengthToPhyloTree tr
+  logInfoNewSection $
+    "Sub sample "
+      <> show (sum chunks)
+      <> " trees with "
+      <> show nL
+      <> " leaves."
   let lvs = Seq.fromList $ leaves tr
   trss <-
     liftIO $
@@ -232,8 +224,8 @@
 
 -- Compute NChilSumStat for a phylogenetic tree.
 toNChildSumStat :: HasLength e => Tree e a -> NChildSumStat
-toNChildSumStat (Node br _ []) = [(getLen br, 1)]
-toNChildSumStat (Node br _ ts) = (getLen br, sumCh) : concat nChSS
+toNChildSumStat (Node br _ []) = [(getLength br, 1)]
+toNChildSumStat (Node br _ ts) = (getLength br, sumCh) : concat nChSS
   where
     nChSS = map toNChildSumStat ts
     sumCh = sum $ map (snd . head) nChSS
diff --git a/src/TLynx/TLynx.hs b/src/TLynx/TLynx.hs
--- a/src/TLynx/TLynx.hs
+++ b/src/TLynx/TLynx.hs
@@ -24,23 +24,17 @@
 import TLynx.Shuffle.Shuffle
 import TLynx.Simulate.Simulate
 
--- TODO: Use a class here (e.g., elynx-wrappable) which defines the extractor function.
-
 -- | Run TLynx with given arguments.
 tlynx :: Arguments CommandArguments -> IO ()
 tlynx c = case local c of
-  Compare _ ->
-    eLynxWrapper c (\(Arguments g (Compare l)) -> Arguments g l) compareCmd
-  Connect _ ->
-    eLynxWrapper c (\(Arguments g (Connect l)) -> Arguments g l) connectCmd
-  Distance _ ->
-    eLynxWrapper c (\(Arguments g (Distance l)) -> Arguments g l) distance
-  Examine _ ->
-    eLynxWrapper c (\(Arguments g (Examine l)) -> Arguments g l) examine
-  Shuffle _ ->
-    eLynxWrapper c (\(Arguments g (Shuffle l)) -> Arguments g l) shuffleCmd
-  Simulate _ ->
-    eLynxWrapper c (\(Arguments g (Simulate l)) -> Arguments g l) simulate
+  Compare l -> eLynxWrapper g l Compare compareCmd
+  Connect l -> eLynxWrapper g l Connect connectCmd
+  Distance l -> eLynxWrapper g l Distance distance
+  Examine l -> eLynxWrapper g l Examine examine
+  Shuffle l -> eLynxWrapper g l Shuffle shuffleCmd
+  Simulate l -> eLynxWrapper g l Simulate simulate
+  where
+    g = global c
 
 -- | Run TLynx, parse arguments from command line.
 rTLynx :: IO ()
diff --git a/tlynx.cabal b/tlynx.cabal
--- a/tlynx.cabal
+++ b/tlynx.cabal
@@ -1,78 +1,79 @@
-cabal-version:      2.2
-name:               tlynx
-version:            0.5.1.1
-license:            GPL-3.0-or-later
-license-file:       LICENSE
-copyright:          Dominik Schrempf (2021)
-maintainer:         dominik.schrempf@gmail.com
-author:             Dominik Schrempf
-homepage:           https://github.com/dschrempf/elynx#readme
-bug-reports:        https://github.com/dschrempf/elynx/issues
-synopsis:           Handle phylogenetic trees
-description:
-    Examine, compare, and simulate phylogenetic trees in a reproducible way. Please see the README on GitHub at <https://github.com/dschrempf/elynx>.
+cabal-version:  2.2
+name:           tlynx
+version:        0.6.0.0
+synopsis:       Handle phylogenetic trees
+description:    Examine, compare, and simulate phylogenetic trees in a reproducible way. Please see the README on GitHub at <https://github.com/dschrempf/elynx>.
+category:       Bioinformatics
+homepage:       https://github.com/dschrempf/elynx#readme
+bug-reports:    https://github.com/dschrempf/elynx/issues
+author:         Dominik Schrempf
+maintainer:     dominik.schrempf@gmail.com
+copyright:      Dominik Schrempf (2021)
+license:        GPL-3.0-or-later
+license-file:   LICENSE
+build-type:     Simple
 
-category:           Bioinformatics
-build-type:         Simple
 extra-source-files:
     README.md
     ChangeLog.md
 
 source-repository head
-    type:     git
-    location: https://github.com/dschrempf/elynx
+  type: git
+  location: https://github.com/dschrempf/elynx
 
 library
-    exposed-modules:
-        TLynx.Compare.Compare
-        TLynx.Compare.Options
-        TLynx.Connect.Connect
-        TLynx.Connect.Options
-        TLynx.Distance.Distance
-        TLynx.Distance.Options
-        TLynx.Examine.Examine
-        TLynx.Examine.Options
-        TLynx.Options
-        TLynx.Parsers
-        TLynx.Shuffle.Options
-        TLynx.Shuffle.Shuffle
-        TLynx.Simulate.Options
-        TLynx.Simulate.Simulate
-        TLynx.TLynx
-
-    hs-source-dirs:   src
-    other-modules:    Paths_tlynx
-    autogen-modules:  Paths_tlynx
-    default-language: Haskell2010
-    ghc-options:      -Wall -Wunused-packages
-    build-depends:
-        aeson >=1.5.6.0,
-        attoparsec >=0.13.2.5,
-        base >=4.7 && <5,
-        bytestring >=0.10.12.0,
-        comonad >=5.0.8,
-        containers >=0.6.2.1,
-        elynx-tools >=0.5.1.1,
-        elynx-tree >=0.5.1.1,
-        gnuplot >=0.5.6.1,
-        lifted-async >=0.10.2,
-        monad-logger >=0.3.36,
-        mwc-random >=0.15.0.1,
-        optparse-applicative >=0.16.1.0,
-        parallel >=3.2.2.0,
-        statistics >=0.15.2.0,
-        text >=1.2.4.1,
-        transformers >=0.5.6.2,
-        vector >=0.12.3.0
+  exposed-modules:
+      TLynx.Compare.Compare
+      TLynx.Compare.Options
+      TLynx.Connect.Connect
+      TLynx.Connect.Options
+      TLynx.Distance.Distance
+      TLynx.Distance.Options
+      TLynx.Examine.Examine
+      TLynx.Examine.Options
+      TLynx.Options
+      TLynx.Parsers
+      TLynx.Shuffle.Options
+      TLynx.Shuffle.Shuffle
+      TLynx.Simulate.Options
+      TLynx.Simulate.Simulate
+      TLynx.TLynx
+  other-modules:
+      Paths_tlynx
+  autogen-modules:
+      Paths_tlynx
+  hs-source-dirs: src
+  ghc-options: -Wall -Wunused-packages
+  build-depends:
+      aeson
+    , async
+    , attoparsec
+    , base >=4.7 && <5
+    , bytestring
+    , comonad
+    , containers
+    , data-default-class
+    , elynx-tools
+    , elynx-tree
+    , gnuplot
+    , mwc-random
+    , optparse-applicative
+    , parallel
+    , statistics
+    , text
+    , transformers
+    , vector
+  default-language: Haskell2010
 
 executable tlynx
-    main-is:          Main.hs
-    hs-source-dirs:   app
-    other-modules:    Paths_tlynx
-    default-language: Haskell2010
-    ghc-options:
-        -Wall -Wunused-packages -threaded -rtsopts -with-rtsopts=-N
-
-    build-depends:
-        base >=4.7 && <5,
-        tlynx -any
+  main-is: Main.hs
+  other-modules:
+      Paths_tlynx
+  autogen-modules:
+      Paths_tlynx
+  hs-source-dirs: app
+  ghc-options: -Wall -Wunused-packages -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , tlynx
+  default-language: Haskell2010
