diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/forest.cabal b/forest.cabal
new file mode 100644
--- /dev/null
+++ b/forest.cabal
@@ -0,0 +1,52 @@
+name:           forest
+version:        0.1
+synopsis:       Tree and Forest types
+license:        MPL-2.0
+license-file:   LICENSE
+author:         Shane O'Brien
+maintainer:     me@shane.sh
+stability:      Experimental
+category:       Control
+cabal-version:  >= 1.6
+homepage:       https://github.com/duairc/forest
+bug-reports:    https://github.com/duairc/forest/issues
+build-type:     Simple
+description:
+  Tree and Forest types, where the leafs and branches of a tree can store
+  different types of data, and forests are parameterised by an arbitrary
+  functor (usually @[]@, but sometimes you might want @NonEmpty@ for example).
+
+Library
+  hs-source-dirs:
+    src
+
+  exposed-modules:
+    Data.Tree.Forest
+
+  build-depends:
+    aeson >= 0.2 && < 1.2,
+    base >= 4.2 && < 5,
+    deepseq >= 1.1 && < 2,
+    hashable >= 1.2 && < 2,
+    profunctors >= 3.2 && < 6,
+    semigroupoids >= 1.0 && < 6,
+    base >= 4 && < 5
+
+  if impl(ghc < 8)
+    build-depends:
+      semigroups >= 0.1 && < 0.20,
+      transformers >= 0.4 && < 0.6
+
+  if impl(ghc < 8.2)
+    build-depends:
+      bifunctors >= 0.1 && < 6
+
+  if impl(ghc >= 7.2 && < 7.6)
+    build-depends: ghc-prim == 0.2.0.0
+
+  ghc-options:
+    -Wall
+
+source-repository head
+  type:     git
+  location: https://github.com/duairc/forest.git
diff --git a/src/Data/Tree/Forest.hs b/src/Data/Tree/Forest.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Tree/Forest.hs
@@ -0,0 +1,678 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE DeriveGeneric #-}
+#endif
+
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+
+#if __GLASGOW_HASKELL__ >= 706
+{-# LANGUAGE PolyKinds #-}
+#endif
+
+#if __GLASGOW_HASKELL__ >= 708
+{-# LANGUAGE TypeFamilies #-}
+#endif
+
+module Data.Tree.Forest
+    ( Tree (Leaf, Node)
+    , Forest (Forest)
+
+    -- * Optics
+    , _Leaf
+    , _Node
+    , _Forest
+
+    -- * Higher order traversals
+    -- ** Trees
+    , hmap
+    , hfoldr
+    , htraverse
+    -- ** Forests
+    , hmap'
+    , hfoldr'
+    , htraverse'
+    )
+where
+
+-- aeson ---------------------------------------------------------------------
+import           Data.Aeson
+                     ( FromJSON
+                     , ToJSON
+                     , Value (Object)
+                     , (.=)
+                     , (.:)
+                     , object
+                     , parseJSON
+                     , toJSON
+                     )
+
+
+-- base ----------------------------------------------------------------------
+#if __GLASGOW_HASKELL__ < 710
+import           Control.Applicative (Applicative, pure, (<$>), (<*>))
+#endif
+import           Control.Applicative (Alternative, (<|>), empty)
+import           Control.Monad
+                     ( MonadPlus
+                     , mzero
+                     , mplus
+                     , msum
+                     )
+#if __GLASGOW_HASKELL__ >= 800
+import           Control.Monad.Fail (MonadFail)
+import qualified Control.Monad.Fail as F (fail)
+#endif
+import           Data.Bifoldable (Bifoldable, bifoldr)
+import           Data.Bifunctor (Bifunctor, bimap)
+import           Data.Bitraversable (Bitraversable, bitraverse)
+#if __GLASGOW_HASKELL__ < 710
+import           Data.Foldable (Foldable, foldr)
+#endif
+import           Data.Functor.Classes
+                     ( Eq1
+                     , Ord1
+                     , Read1
+                     , Show1
+                     , Eq2
+                     , Ord2
+                     , Read2
+                     , Show2
+                     , liftCompare
+                     , liftCompare2
+                     , liftEq
+                     , liftEq2
+                     , liftReadList2
+                     , liftReadsPrec
+                     , liftReadsPrec2
+                     , liftShowList2
+                     , liftShowsPrec
+                     , liftShowsPrec2
+                     , readsData
+                     , readsUnaryWith
+                     , showsUnaryWith
+                     )
+#if __GLASGOW_HASKELL__ < 710
+import           Data.Monoid (Monoid, mappend, mconcat, mempty)
+#endif
+import           Data.Semigroup (Semigroup, (<>))
+#if __GLASGOW_HASKELL__ < 710
+import           Data.Traversable
+                     ( Traversable
+                     , traverse
+                     )
+#endif
+#if __GLASGOW_HASKELL__ >= 708
+import           Data.Typeable (Typeable)
+#endif
+#if __GLASGOW_HASKELL__ >= 708
+import           GHC.Exts (IsList, Item, fromList, toList)
+#endif
+#if __GLASGOW_HASKELL__ >= 702
+import           GHC.Generics
+                     ( Generic
+#if __GLASGOW_HASKELL__ >= 706
+                     , Generic1
+#endif
+                     )
+#endif
+#if __GLASGOW_HASKELL__ < 710
+import           Prelude hiding (foldr)
+#endif
+
+
+-- deepseq -------------------------------------------------------------------
+import           Control.DeepSeq (NFData, rnf)
+
+
+-- hashable ------------------------------------------------------------------
+import           Data.Hashable (Hashable, hashWithSalt)
+
+
+-- profunctors ---------------------------------------------------------------
+import           Data.Profunctor (Choice, Profunctor, dimap, right')
+
+
+-- semigroupoids -------------------------------------------------------------
+import           Data.Functor.Alt (Alt, (<!>))
+import           Data.Functor.Apply (Apply, (<.>))
+import           Data.Functor.Bind (Bind, (>>-), join)
+import           Data.Functor.Plus (Plus, zero)
+
+
+------------------------------------------------------------------------------
+data Tree f s a = Leaf !a | Node !s (Forest f s a)
+  deriving
+    (
+#if __GLASGOW_HASKELL__ >= 702
+      Generic
+#if __GLASGOW_HASKELL__ >= 706
+    , Generic1
+#endif
+#endif
+#if __GLASGOW_HASKELL__ >= 708
+    , Typeable
+#endif
+    )
+deriving instance (Eq a, Eq s, Eq (Forest f s a)) => Eq (Tree f s a)
+deriving instance (Ord a, Ord s, Ord (Forest f s a), Ord (f (Tree f s a))) =>
+    Ord (Tree f s a)
+deriving instance (Read a, Read s, Read (Forest f s a)) => Read (Tree f s a)
+deriving instance (Show a, Show s, Show (Forest f s a)) => Show (Tree f s a)
+
+
+------------------------------------------------------------------------------
+_Leaf :: (Choice p, Applicative f)
+    => p a (f a)
+    -> p (Tree g s a) (f (Tree g s a))
+_Leaf = dimap from (either pure (fmap to)) . right'
+  where
+    from (Leaf a) = Right a
+    from t = Left t
+    to = Leaf
+{-# INLINE _Leaf #-}
+
+
+------------------------------------------------------------------------------
+_Node :: (Choice p, Applicative f)
+    => p (s, Forest g s a) (f (s, Forest g s a))
+    -> p (Tree g s a) (f (Tree g s a))
+_Node = dimap from (either pure (fmap to)) . right'
+  where
+    from (Node s ts) = Right (s, ts)
+    from t = Left t
+    to = uncurry Node
+{-# INLINE _Node #-}
+
+
+------------------------------------------------------------------------------
+instance (NFData s, NFData a, NFData (f (Tree f s a))) =>
+    NFData (Tree f s a)
+  where
+    rnf (Leaf a) = rnf a
+    rnf (Node s ts) = rnf s `seq` rnf ts
+    {-# INLINE rnf #-}
+
+
+------------------------------------------------------------------------------
+instance (Hashable s, Hashable a, Hashable (f (Tree f s a))) =>
+    Hashable (Tree f s a)
+  where
+    hashWithSalt s (Leaf a) = hashWithSalt s a
+    hashWithSalt s (Node s' ts) = hashWithSalt (hashWithSalt s s') ts
+    {-# INLINE hashWithSalt #-}
+
+
+------------------------------------------------------------------------------
+instance Functor f => Bifunctor (Tree f) where
+    bimap _ g (Leaf a) = Leaf (g a)
+    bimap f g (Node s ts) = Node (f s) (bimap f g ts)
+    {-# INLINE bimap #-}
+
+
+------------------------------------------------------------------------------
+instance Foldable f => Bifoldable (Tree f) where
+    bifoldr _ g b (Leaf a) = g a b
+    bifoldr f g b (Node s ts) = f s $ bifoldr f g b ts
+    {-# INLINE bifoldr #-}
+
+
+------------------------------------------------------------------------------
+instance Traversable f => Bitraversable (Tree f) where
+    bitraverse _ g (Leaf a) = Leaf <$> g a
+    bitraverse f g (Node s ts) = Node <$> f s <*> bitraverse f g ts
+    {-# INLINE bitraverse #-}
+
+
+------------------------------------------------------------------------------
+instance Functor f => Functor (Tree f s) where
+    fmap f (Leaf a) = Leaf (f a)
+    fmap f (Node s ts) = Node s (fmap f ts)
+    {-# INLINE fmap #-}
+
+
+------------------------------------------------------------------------------
+instance Foldable f => Foldable (Tree f s) where
+    foldr f b (Leaf a) = f a b
+    foldr f b (Node _ ts) = foldr f b ts
+    {-# INLINE foldr #-}
+
+
+------------------------------------------------------------------------------
+instance Traversable f => Traversable (Tree f s) where
+    traverse f (Leaf a) = Leaf <$> f a
+    traverse f (Node s ts) = Node s <$> traverse f ts
+    {-# INLINE traverse #-}
+
+
+------------------------------------------------------------------------------
+instance Functor f => Apply (Tree f s) where
+    Leaf f <.> Leaf a = Leaf (f a)
+    Leaf f <.> Node s ts = Node s (fmap f ts)
+    Node s (Forest ts) <.> f = Node s $ Forest $ fmap (<.> f) ts
+    {-# INLINE (<.>) #-}
+
+
+------------------------------------------------------------------------------
+instance Functor f => Bind (Tree f s) where
+    Leaf a >>- f = f a
+    Node s (Forest ts) >>- f = Node s $ Forest $ fmap (>>- f) ts
+    {-# INLINE (>>-) #-}
+
+
+------------------------------------------------------------------------------
+instance Functor f => Applicative (Tree f s) where
+    pure = Leaf
+    {-# INLINE pure #-}
+    (<*>) = (<.>)
+    {-# INLINE (<*>) #-}
+
+
+------------------------------------------------------------------------------
+instance Functor f => Monad (Tree f s) where
+    return = pure
+    {-# INLINE return #-}
+    (>>=) = (>>-)
+    {-# INLINE (>>=) #-}
+
+
+------------------------------------------------------------------------------
+instance (ToJSON s, ToJSON a, ToJSON (f (Tree f s a))) =>
+    ToJSON (Tree f s a)
+  where
+    toJSON (Leaf a) = object
+        [ "value" .= toJSON a
+        ]
+    toJSON (Node s ts) = object
+        [ "value" .= toJSON s
+        , "children" .= toJSON ts
+        ]
+    {-# INLINE toJSON #-}
+
+
+------------------------------------------------------------------------------
+instance (FromJSON s, FromJSON a, FromJSON (f (Tree f s a))) =>
+    FromJSON (Tree f s a)
+  where
+    parseJSON (Object o) = msum
+        [ Node <$> o .: "value" <*> o .: "children"
+        , Leaf <$> o .: "value"
+        ]
+    parseJSON _ = empty
+    {-# INLINE parseJSON #-}
+
+
+------------------------------------------------------------------------------
+instance Eq1 f => Eq2 (Tree f) where
+    liftEq2 _ eqa (Leaf a) (Leaf b) = eqa a b
+    liftEq2 eqs eqa (Node s ts) (Node t tt) = and
+        [ eqs s t
+        , liftEq2 eqs eqa ts tt
+        ]
+    liftEq2 _ _ _ _ = False
+    {-# INLINE liftEq2 #-}
+
+
+------------------------------------------------------------------------------
+instance Ord1 f => Ord2 (Tree f) where
+    liftCompare2 _ cmpa (Leaf a) (Leaf b) = cmpa a b
+    liftCompare2 cmps cmpa (Node s ts) (Node t tt) = mconcat
+        [ cmps s t
+        , liftCompare2 cmps cmpa ts tt
+        ]
+    liftCompare2 _ _ _ _ = mempty
+    {-# INLINE liftCompare2 #-}
+
+
+------------------------------------------------------------------------------
+instance Read1 f => Read2 (Tree f) where
+    liftReadsPrec2 rds rdss rda rdas p = readParen (p > 10) $ \s -> msum
+        [ do
+            ("Leaf", s') <- lex s
+            (a, s'') <- rda 11 s'
+            pure (Leaf a, s'')
+        , do
+            ("Node", s') <- lex s
+            (a, s'') <- rds 11 s'
+            (ts, s''') <- liftReadsPrec2 rds rdss rda rdas 11 s''
+            pure (Node a ts, s''')
+        ]
+    {-# INLINE liftReadsPrec2 #-}
+
+
+------------------------------------------------------------------------------
+instance Show1 f => Show2 (Tree f) where
+    liftShowsPrec2 _ _ shwa _ p (Leaf a) = showParen (p > 10) $
+        showString "Leaf " . shwa 11 a
+    liftShowsPrec2 shws shwss shwa shwas p (Node s ts) = showParen (p > 10)
+        $ foldr (.) id
+            [ showString "Node "
+            , shws 11 s
+            , showString " "
+            , liftShowsPrec2 shws shwss shwa shwas 11 ts
+            ]
+    {-# INLINE liftShowsPrec2 #-}
+
+
+------------------------------------------------------------------------------
+instance (Eq1 f, Eq s) => Eq1 (Tree f s) where
+    liftEq = liftEq2 (==)
+    {-# INLINE liftEq #-}
+
+
+------------------------------------------------------------------------------
+instance (Ord1 f, Ord s) => Ord1 (Tree f s) where
+    liftCompare = liftCompare2 compare
+    {-# INLINE liftCompare #-}
+
+
+------------------------------------------------------------------------------
+instance (Read1 f, Read s) => Read1 (Tree f s) where
+    liftReadsPrec = liftReadsPrec2 readsPrec readList
+    {-# INLINE liftReadsPrec #-}
+
+
+------------------------------------------------------------------------------
+instance (Show1 f, Show s) => Show1 (Tree f s) where
+    liftShowsPrec = liftShowsPrec2 showsPrec showList
+    {-# INLINE liftShowsPrec #-}
+
+
+------------------------------------------------------------------------------
+newtype Forest f s a = Forest (f (Tree f s a))
+  deriving
+    (
+#if __GLASGOW_HASKELL__ >= 702
+      Generic
+#if __GLASGOW_HASKELL__ >= 706
+    , Generic1
+#endif
+#endif
+#if __GLASGOW_HASKELL__ >= 708
+    , Typeable
+#endif
+    )
+deriving instance Eq (f (Tree f s a)) => Eq (Forest f s a)
+deriving instance Ord (f (Tree f s a)) => Ord (Forest f s a)
+deriving instance Read (f (Tree f s a)) => Read (Forest f s a)
+deriving instance Show (f (Tree f s a)) => Show (Forest f s a)
+
+
+------------------------------------------------------------------------------
+_Forest :: (Profunctor p, Functor f)
+    => p (g (Tree g s a)) (f (g (Tree g s a)))
+    -> p (Forest g s a) (f (Forest g s a))
+_Forest = dimap from (fmap to)
+  where
+    from (Forest a) = a
+    to = Forest
+{-# INLINE _Forest #-}
+
+
+------------------------------------------------------------------------------
+instance (NFData a, NFData s, NFData (f (Tree f s a))) =>
+    NFData (Forest f s a)
+  where
+    rnf (Forest ts) = rnf ts
+    {-# INLINE rnf #-}
+
+
+------------------------------------------------------------------------------
+instance (Hashable a, Hashable s, Hashable (f (Tree f s a))) =>
+    Hashable (Forest f s a)
+  where
+    hashWithSalt s (Forest ts) = hashWithSalt s ts
+    {-# INLINE hashWithSalt #-}
+
+
+#if __GLASGOW_HASKELL__ >= 708
+------------------------------------------------------------------------------
+instance IsList (f (Tree f s a)) => IsList (Forest f s a) where
+    type Item (Forest f s a) = Item (f (Tree f s a))
+    toList (Forest ts) = toList ts
+    {-# INLINE toList #-}
+    fromList = Forest . fromList
+    {-# INLINE fromList #-}
+
+
+#endif
+------------------------------------------------------------------------------
+instance Functor f => Bifunctor (Forest f) where
+    bimap f g (Forest ts) = Forest (fmap (bimap f g) ts)
+    {-# INLINE bimap #-}
+
+
+------------------------------------------------------------------------------
+instance Foldable f => Bifoldable (Forest f) where
+    bifoldr f g b (Forest ts) = foldr (flip (bifoldr f g)) b ts
+    {-# INLINE bifoldr #-}
+
+
+------------------------------------------------------------------------------
+instance Traversable f => Bitraversable (Forest f) where
+    bitraverse f g (Forest ts) = Forest <$> traverse (bitraverse f g) ts
+    {-# INLINE bitraverse #-}
+
+
+------------------------------------------------------------------------------
+instance Functor f => Functor (Forest f s) where
+    fmap f (Forest ts) = Forest (fmap (fmap f) ts)
+    {-# INLINE fmap #-}
+
+
+------------------------------------------------------------------------------
+instance Foldable f => Foldable (Forest f s) where
+    foldr f b (Forest ts) = foldr (flip (foldr f)) b ts
+    {-# INLINE foldr #-}
+
+
+------------------------------------------------------------------------------
+instance Traversable f => Traversable (Forest f s) where
+    traverse f (Forest ts) = Forest <$> traverse (traverse f) ts
+    {-# INLINE traverse #-}
+
+
+------------------------------------------------------------------------------
+instance Apply f => Apply (Forest f s) where
+    Forest fs <.> Forest as = Forest $ (<.>) <$> fs <.> as
+    {-# INLINE (<.>) #-}
+
+
+------------------------------------------------------------------------------
+instance Alt f => Alt (Forest f s) where
+    Forest as <!> Forest bs = Forest $ as <!> bs
+    {-# INLINE (<!>) #-}
+
+
+------------------------------------------------------------------------------
+instance Plus f => Plus (Forest f s) where
+    zero = Forest zero
+    {-# INLINE zero #-}
+
+
+------------------------------------------------------------------------------
+instance (Applicative f, Bind f, Traversable f) => Bind (Forest f s) where
+    Forest ts >>- f = Forest $ ts >>- fmap join . traverse (runForest . f)
+      where
+        runForest (Forest tt) = tt
+    {-# INLINE (>>-) #-}
+
+
+------------------------------------------------------------------------------
+instance Applicative f => Applicative (Forest f s) where
+    pure = Forest . pure . pure
+    {-# INLINE pure #-}
+    Forest fs <*> Forest as = Forest $ (<*>) <$> fs <*> as
+    {-# INLINE (<*>) #-}
+
+
+------------------------------------------------------------------------------
+instance Alternative f => Alternative (Forest f s) where
+    empty = Forest empty
+    {-# INLINE empty #-}
+    Forest as <|> Forest bs = Forest $ as <|> bs
+    {-# INLINE (<|>) #-}
+
+
+------------------------------------------------------------------------------
+instance (Applicative f, Monad f, Traversable f) => Monad (Forest f s) where
+    return = pure
+    {-# INLINE return #-}
+    Forest ts >>= f = Forest $ ts >>= fmap join . traverse (runForest . f)
+      where
+        runForest (Forest tt) = tt
+    {-# INLINE (>>=) #-}
+    fail = Forest . fail
+    {-# INLINE fail #-}
+
+
+#if __GLASGOW_HASKELL__ >= 800
+------------------------------------------------------------------------------
+instance (MonadFail f, Traversable f) => MonadFail (Forest f s) where
+    fail = Forest . F.fail
+    {-# INLINE fail #-}
+
+
+#endif
+------------------------------------------------------------------------------
+instance (Alternative f, Monad f, Traversable f) => MonadPlus (Forest f s)
+  where
+    mzero = empty
+    {-# INLINE mzero #-}
+    mplus = (<|>)
+    {-# INLINE mplus #-}
+
+
+------------------------------------------------------------------------------
+instance Alt f => Semigroup (Forest f s a) where
+    (<>) = (<!>)
+    {-# INLINE (<>) #-}
+
+
+------------------------------------------------------------------------------
+instance Alternative f => Monoid (Forest f s a) where
+    mempty = empty
+    {-# INLINE mempty #-}
+    mappend = (<|>)
+    {-# INLINE mappend #-}
+
+
+------------------------------------------------------------------------------
+instance (ToJSON s, ToJSON a, ToJSON (f (Tree f s a))) =>
+    ToJSON (Forest f s a)
+  where
+    toJSON (Forest ts) = toJSON ts
+    {-# INLINE toJSON #-}
+
+
+------------------------------------------------------------------------------
+instance (FromJSON s, FromJSON a, FromJSON (f (Tree f s a))) =>
+    FromJSON (Forest f s a)
+  where
+    parseJSON = fmap Forest . parseJSON
+    {-# INLINE parseJSON #-}
+
+
+------------------------------------------------------------------------------
+instance Eq1 f => Eq2 (Forest f) where
+    liftEq2 eqs eqa (Forest ts) (Forest tt) = liftEq (liftEq2 eqs eqa) ts tt
+    {-# INLINE liftEq2 #-}
+
+
+------------------------------------------------------------------------------
+instance Ord1 f => Ord2 (Forest f) where
+    liftCompare2 cmps cmpa (Forest ts) (Forest tt) =
+        liftCompare (liftCompare2 cmps cmpa) ts tt
+    {-# INLINE liftCompare2 #-}
+
+
+------------------------------------------------------------------------------
+instance Read1 f => Read2 (Forest f) where
+    liftReadsPrec2 rds rdss rda rdas = readsData $
+        readsUnaryWith
+            (liftReadsPrec
+                (liftReadsPrec2 rds rdss rda rdas)
+                (liftReadList2 rds rdss rda rdas))
+            "Forest"
+            Forest
+    {-# INLINE liftReadsPrec2 #-}
+
+
+------------------------------------------------------------------------------
+instance Show1 f => Show2 (Forest f) where
+    liftShowsPrec2 shws shwss shwa shwas p (Forest fs) =
+        showsUnaryWith
+            (liftShowsPrec
+                (liftShowsPrec2 shws shwss shwa shwas)
+                (liftShowList2 shws shwss shwa shwas))
+            "Forest"
+            p
+            fs
+    {-# INLINE liftShowsPrec2 #-}
+
+
+------------------------------------------------------------------------------
+instance (Eq1 f, Eq s) => Eq1 (Forest f s) where
+    liftEq = liftEq2 (==)
+    {-# INLINE liftEq #-}
+
+
+------------------------------------------------------------------------------
+instance (Ord1 f, Ord s) => Ord1 (Forest f s) where
+    liftCompare = liftCompare2 compare
+    {-# INLINE liftCompare #-}
+
+
+------------------------------------------------------------------------------
+instance (Read1 f, Read s) => Read1 (Forest f s) where
+    liftReadsPrec = liftReadsPrec2 readsPrec readList
+    {-# INLINE liftReadsPrec #-}
+
+
+------------------------------------------------------------------------------
+instance (Show1 f, Show s) => Show1 (Forest f s) where
+    liftShowsPrec = liftShowsPrec2 showsPrec showList
+    {-# INLINE liftShowsPrec #-}
+
+
+------------------------------------------------------------------------------
+hmap :: Functor f => (forall x. f x -> g x) -> Tree f s a -> Tree g s a
+hmap _ (Leaf a) = Leaf a
+hmap f (Node s ts) = Node s (hmap' f ts)
+
+
+------------------------------------------------------------------------------
+hfoldr :: Foldable f => (forall x. f x -> b -> b) -> b -> Tree f s a -> b
+hfoldr _ b (Leaf _) = b
+hfoldr f b (Node _ ts) = hfoldr' f b ts
+
+
+------------------------------------------------------------------------------
+htraverse :: (Traversable f, Applicative h, Monad h)
+    => (forall x. f x -> h (g x)) -> Tree f s a -> h (Tree g s a)
+htraverse _ (Leaf a) = pure (Leaf a)
+htraverse f (Node s ts) = Node s <$> htraverse' f ts
+
+
+------------------------------------------------------------------------------
+hmap' :: Functor f => (forall x. f x -> g x) -> Forest f s a -> Forest g s a
+hmap' f (Forest fs) = Forest (f (fmap (hmap f) fs))
+
+
+------------------------------------------------------------------------------
+hfoldr' :: Foldable f => (forall x. f x -> b -> b) -> b -> Forest f s a -> b
+hfoldr' f b (Forest fs) = f fs (foldr (flip (hfoldr f)) b fs)
+
+
+------------------------------------------------------------------------------
+htraverse' :: (Traversable f, Applicative h, Monad h)
+    => (forall x. f x -> h (g x)) -> Forest f s a -> h (Forest g s a)
+htraverse' f (Forest fs) = fmap Forest $ traverse (htraverse f) fs >>= f
