diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Changelog for polysemy-severl
+
+## v0.1.0.0
+
+* Imported `Polysemy.Several` from polysemy-zoo.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright Sandy Maguire (c) 2019
+Copyright Daniel Firth (c) 2021
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Sandy Maguire nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+# polysemy-several
+
+runSeveral interpreter for polysemy, originally taken from
+[polysemy-zoo](https://hackage.haskell.org/package/polysemy-zoo).
diff --git a/polysemy-several.cabal b/polysemy-several.cabal
new file mode 100644
--- /dev/null
+++ b/polysemy-several.cabal
@@ -0,0 +1,37 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.34.4.
+--
+-- see: https://github.com/sol/hpack
+
+name:           polysemy-several
+version:        0.1.0.0
+synopsis:       Run several effects at once, taken from the polysemy-zoo.
+description:    Run several effects at once, taken from the polysemy-zoo.
+category:       Polysemy
+author:         Daniel Firth
+maintainer:     dan.firth@homotopic.tech
+copyright:      2020 Daniel Firth
+license:        MIT
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://gitlab.com/homotopic-tech/polysemy-several
+
+library
+  exposed-modules:
+      Polysemy.Several
+  other-modules:
+      Paths_polysemy_several
+  hs-source-dirs:
+      src
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints
+  build-depends:
+      base >=4.7 && <4.16
+    , polysemy >=1.3.0.0 && <1.7
+  default-language: Haskell2010
diff --git a/src/Polysemy/Several.hs b/src/Polysemy/Several.hs
new file mode 100644
--- /dev/null
+++ b/src/Polysemy/Several.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+module Polysemy.Several
+  ( HList (..),
+    TypeMap,
+    Append,
+    runSeveral,
+  )
+where
+
+import Data.Kind
+import Polysemy
+
+------------------------------------------------------------------------------
+
+-- | A list capable of storing values of different types. Creating an HList
+-- looks like.
+--
+-- > 1 ::: "test" ::: True ::: HNil
+infixr 5 :::
+
+data HList a where
+  HNil :: HList '[]
+  (:::) :: a -> HList (b :: [Type]) -> HList (a ': b)
+
+------------------------------------------------------------------------------
+
+-- | A map function over type level lists. For example, the following two
+-- lines are equivalent:
+--
+-- > TypeMap Reader [Int, String, False]
+-- > [Reader Int, Reader String, Reader Bool]
+type family TypeMap (f :: a -> b) (xs :: [a]) where
+  TypeMap _ '[] = '[]
+  TypeMap f (x ': xs) = f x ': TypeMap f xs
+
+------------------------------------------------------------------------------
+
+-- | Type-level append.
+--
+-- > Append [Int, String] [Bool]
+-- > [Int, String, Bool]
+type family Append (a :: [t]) (b :: [t]) where
+  Append '[] b = b
+  Append (a ': as) b = a ': Append as b
+
+------------------------------------------------------------------------------
+
+-- | A helper function for building new runners which accept HLists intsead of
+-- individual elements. If you would normally write
+--
+-- > f 5 . f "Text" . f True
+--
+-- then this function can turn that into
+--
+-- > runSeveral f (True ::: "Text" ::: 5 ::: HNil)
+--
+-- For example, a runReaders function could be implemented as:
+--
+-- > runReaders :: HList t -> Sem (TypeConcat (TypeMap Reader t) r) a -> Sem r a
+-- > runReaders = runSeveral runReader
+--
+-- @since 0.1.0.0
+runSeveral ::
+  (forall r' k x. k -> Sem (e k ': r') x -> Sem r' x) ->
+  HList t ->
+  Sem (Append (TypeMap e t) r) a ->
+  Sem r a
+runSeveral f (a ::: as) = runSeveral f as . f a
+runSeveral _ HNil = id
