diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for autoshow1
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2018 - 2023, Koji Miyazato
+
+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 Koji Miyazato 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/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/auto-lift-classes.cabal b/auto-lift-classes.cabal
new file mode 100644
--- /dev/null
+++ b/auto-lift-classes.cabal
@@ -0,0 +1,35 @@
+cabal-version:       2.0
+name:                auto-lift-classes
+version:             1
+synopsis:            Deriving (Show|Read)(1|2)
+description:         Deriving (Show|Read)(1|2) from the usual, stock deriveable
+                     instances like @Show a => Show (f a)@.
+license:             BSD3
+license-file:        LICENSE
+author:              Koji Miyazato
+maintainer:          viercc@gmail.com
+copyright:           (c) 2018-2023, Koji Miyazato
+category:            Data, Reflection
+build-type:          Simple
+extra-source-files:  CHANGELOG.md
+tested-with:         GHC ==8.6.5, GHC ==8.8.4, GHC ==8.10.7, GHC ==9.0.2, GHC ==9.2.5, GHC ==9.4.4
+
+source-repository head
+  type:     git
+  location: https://github.com/viercc/auto-lift-classes
+  branch:   master
+
+library
+  exposed-modules:    AutoLift, AutoLift.Machinery
+  build-depends:      base >= 4.12 && < 5.0,
+                      reflection >= 1.0
+  hs-source-dirs:     src
+  default-language:   Haskell2010
+  ghc-options:        -Wall -Wcompat
+
+test-suite run-example
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      example
+  main-is:             test.hs
+  build-depends:       base, auto-lift-classes
+  default-language:    Haskell2010
diff --git a/example/test.hs b/example/test.hs
new file mode 100644
--- /dev/null
+++ b/example/test.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE RoleAnnotations #-}
+module Main where
+
+import Data.Functor.Classes
+import Text.Read
+
+import AutoLift
+
+data Test a = Test Int a [a]
+    deriving (Show, Read, Eq)
+    deriving (Show1, Read1) via (Reflected1 Test)
+
+{-
+
+-- The following does not compile due to type role annotation
+
+data BadTest a = BadTest a [a]
+    deriving (Show, Read, Eq)
+    deriving (Show1, Read1) via (Reflected1 BadTest)
+
+type role BadTest nominal
+
+-}
+
+test :: Test Char
+test = Test 1 'a' "bcd"
+
+testShow :: String
+testShow = show test
+
+testShow1 :: String
+testShow1 = showsPrec1 0 test ""
+
+readStr :: String
+readStr = "Test 2 'e' \"fg\"   "
+
+testRead :: [(Test Char, String)]
+testRead = reads readStr
+
+testRead1 :: [(Test Char, String)]
+testRead1 = readsPrec1 0 readStr
+
+data Crest a b = Crest Int [a] [b]
+    deriving (Show, Read, Eq)
+    deriving (Show1, Read1) via (Reflected1 (Crest a))
+    deriving (Show2, Read2) via (Reflected2 Crest)
+
+crest :: Crest Char Bool
+crest = Crest 2 "foo" [False, True]
+
+crestShow, crestShow1, crestShow2 :: String
+crestShow = show crest
+crestShow1 = showsPrec1 0 crest ""
+crestShow2 = showsPrec2 0 crest ""
+
+crestReadStr :: String
+crestReadStr = "Crest 3 \"foo\" [True] rest of text"
+
+crestRead, crestRead1, crestRead2 :: [(Crest Char Bool, String)]
+crestRead = reads crestReadStr
+crestRead1 = readsPrec1 0 crestReadStr
+crestRead2 = readsPrec2 0 crestReadStr
+
+main :: IO ()
+main = putStrLn . unlines $
+  [ "testShow:  " ++ show testShow
+  , "testShow1: " ++ show testShow1
+  , "testShow == testShow1: " ++ show (testShow == testShow1)
+  , ""
+  , "testRead:  " ++ show testRead
+  , "testRead1: " ++ show testRead1
+  , "testRead == testRead1: " ++ show (testRead == testRead1)
+  , ""
+  , "crestShow:  " ++ show crestShow
+  , "crestShow1: " ++ show crestShow1
+  , "crestShow2: " ++ show crestShow2
+  , "crestShow == crestShow1: " ++ show (crestShow == crestShow1)
+  , "crestShow == crestShow2: " ++ show (crestShow == crestShow2)
+  , ""
+  , "crestRead:  " ++ show crestRead
+  , "crestRead1: " ++ show crestRead1
+  , "crestRead2: " ++ show crestRead2
+  , "crestRead == crestRead1: " ++ show (crestRead == crestRead1)
+  , "crestRead == crestRead2: " ++ show (crestRead == crestRead2)
+  ]
diff --git a/src/AutoLift.hs b/src/AutoLift.hs
new file mode 100644
--- /dev/null
+++ b/src/AutoLift.hs
@@ -0,0 +1,158 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuantifiedConstraints #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+-- | Derive lifted version of 'Show' or 'Read' classes, like @'Show1' f@ or @'Read1' f@,
+--   from derivable instance @forall a. Show a => Show (f a)@.
+module AutoLift
+  ( Reflected1 (..),
+    Reflected2 (..),
+
+    -- * Reexports
+    Show1 (..),
+    Read (..),
+    Read1 (..),
+    ReadPrec,
+  )
+where
+
+import AutoLift.Machinery
+import Data.Coerce
+import Data.Functor.Classes
+import Text.Read
+
+-- | A newtype wrapper to derive @'Show1' f@ and @'Read1' f@ from the following,
+--   often derivable instance.
+--
+--   > instance Show a => Show (f a)
+--   > instance Read a => Read (f a)
+--
+-- ==== Example
+--
+-- Suppose you define a new type constructor @Foo@, and
+-- derived its @Show@ instance.
+--
+-- >>> data Foo a = Foo [a] Int a deriving Show
+--
+-- The derived @Show (Foo a)@ instance is defined for all @a@ with @Show a@ instance.
+--
+-- > instance Show a => Show (Foo a)
+--
+-- @Reflected1@ allows you to derive @'Show1' Foo@ instance from the above instance.
+--
+-- >>> :set -XStandaloneDeriving -XDerivingVia
+-- >>> deriving via (Reflected1 Foo) instance Show1 Foo
+--
+-- Let's try the derived @Show1@ instance, by showing @Foo Bool@, where
+-- @True@ is shown as @yes@ and @False@ as @no@, instead of the normal @Show Bool@ instance.
+--
+-- >>> import Text.Show (showListWith)
+-- >>> let yesno b = (++) (if b then "yes" else "no")
+-- >>> liftShowsPrec (const yesno) (showListWith yesno) 0 (Foo [True, False] 5 False) ""
+-- "Foo [yes,no] 5 no"
+newtype Reflected1 f a = Reflected1 (f a)
+
+wrapShowDict1 :: ShowDict (f a) -> ShowDict (Reflected1 f a)
+wrapShowDict1 = coerce
+
+wrapReadDict1 :: ReadDict (f a) -> ReadDict (Reflected1 f a)
+wrapReadDict1 = coerce
+
+instance
+  ( forall a. Show a => Show (f a),
+    forall xx yy. Coercible xx yy => Coercible (f xx) (f yy)
+  ) =>
+  Show1 (Reflected1 f)
+  where
+  liftShowsPrec showsPrecB showListB =
+    let showFB = wrapShowDict1 $ autoShow1 @f (ShowDict showsPrecB showListB)
+     in _showsPrec showFB
+  liftShowList showsPrecB showListB =
+    let showFB = wrapShowDict1 $ autoShow1 @f (ShowDict showsPrecB showListB)
+     in _showList showFB
+
+instance
+  ( forall a. Read a => Read (f a),
+    forall xx yy. Coercible xx yy => Coercible (f xx) (f yy)
+  ) =>
+  Read1 (Reflected1 f)
+  where
+  liftReadPrec readPrecB readListPrecB =
+    let readFB = wrapReadDict1 $ autoRead1 @f (ReadDict readPrecB readListPrecB)
+     in _readPrec readFB
+
+  liftReadListPrec readPrecB readListPrecB =
+    let readFB = wrapReadDict1 $ autoRead1 @f (ReadDict readPrecB readListPrecB)
+     in _readListPrec readFB
+
+-- | A newtype wrapper to derive @'Show2' f@ and @'Read2' f@ from the following,
+--   often derivable instance.
+--
+--   > instance (Show a, Show b) => Show (f a b)
+--   > instance (Read a, Read b) => Read (f a b)
+--
+-- ==== Example
+--
+-- Suppose you define a new type constructor @Bar@, and
+-- derived its @Show@ instance.
+--
+-- >>> data Bar a b = Bar [(Int,a,b)] deriving Show
+--
+-- The derived @Show (Bar a b)@ instance is defined for all @a@ and @b@ with @Show@ instances.
+--
+-- > instance (Show a, Show b) => Show (Bar a b)
+--
+-- @Reflected2@ allows you to derive @'Show2' Bar@ instance from the above instance.
+--
+-- >>> :set -XStandaloneDeriving -XDerivingVia
+-- >>> deriving via (Reflected2 Bar) instance Show2 Bar
+--
+-- Let's try the derived @Show2@ instance by showing @Bar Bool Char@, where
+-- @True@ is shown as @yes@ and @False@ as @no@, instead of the normal @Show Bool@ instance.
+--
+-- >>> import Text.Show (showListWith)
+-- >>> let yesno b = (++) (if b then "yes" else "no")
+-- >>> liftShowsPrec2 (const yesno) (showListWith yesno) showsPrec showList 0 (Bar [(1, True, 'A'), (2, False, 'B')]) ""
+-- "Bar [(1,yes,'A'),(2,no,'B')]"
+newtype Reflected2 f a b = Reflected2 (f a b)
+
+wrapShowDict2 :: ShowDict (f a b) -> ShowDict (Reflected2 f a b)
+wrapShowDict2 = coerce
+
+wrapReadDict2 :: ReadDict (f a b) -> ReadDict (Reflected2 f a b)
+wrapReadDict2 = coerce
+
+instance
+  ( forall a b. (Show a, Show b) => Show (f a b),
+    forall x1 y1 x2 y2.
+    (Coercible x1 y1, Coercible x2 y2) =>
+    Coercible (f x1 x2) (f y1 y2)
+  ) =>
+  Show2 (Reflected2 f)
+  where
+  liftShowsPrec2 showsPrecC showListC showsPrecD showListD =
+    let showFCD = wrapShowDict2 $ autoShow2 @f (ShowDict showsPrecC showListC) (ShowDict showsPrecD showListD)
+     in _showsPrec showFCD
+  liftShowList2 showsPrecC showListC showsPrecD showListD =
+    let showFCD = wrapShowDict2 $ autoShow2 @f (ShowDict showsPrecC showListC) (ShowDict showsPrecD showListD)
+     in _showList showFCD
+
+instance
+  ( forall a b. (Read a, Read b) => Read (f a b),
+    forall x1 y1 x2 y2.
+    (Coercible x1 y1, Coercible x2 y2) =>
+    Coercible (f x1 x2) (f y1 y2)
+  ) =>
+  Read2 (Reflected2 f)
+  where
+  liftReadPrec2 readPrecC readListPrecC readPrecD readListPrecD =
+    let readFCD = wrapReadDict2 $ autoRead2 @f (ReadDict readPrecC readListPrecC) (ReadDict readPrecD readListPrecD)
+     in _readPrec readFCD
+
+  liftReadListPrec2 readPrecC readListPrecC readPrecD readListPrecD =
+    let readFCD = wrapReadDict2 $ autoRead2 @f (ReadDict readPrecC readListPrecC) (ReadDict readPrecD readListPrecD)
+     in _readListPrec readFCD
diff --git a/src/AutoLift/Machinery.hs b/src/AutoLift/Machinery.hs
new file mode 100644
--- /dev/null
+++ b/src/AutoLift/Machinery.hs
@@ -0,0 +1,129 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuantifiedConstraints #-}
+{-# LANGUAGE UndecidableInstances #-}
+-- | Internal workings of "AutoLift". You usually don't need to import
+--   this module.
+module AutoLift.Machinery (
+    AdHoc(..),
+    ShowDict(..), showDict, autoShow1, autoShow2,
+    ReadDict(..), readDict, autoRead1, autoRead2
+) where
+
+import Data.Reflection
+import Data.Proxy
+import Data.Coerce
+import Text.Read
+
+-- | Apply ad hoc instances on type @a@.
+newtype AdHoc s a = AdHoc a
+
+-- * Show
+
+-- | Injected dictionary of Show
+data ShowDict a = ShowDict
+  { _showsPrec :: Int -> a -> ShowS
+  , _showList :: [a] -> ShowS
+  }
+
+showDict :: forall a. Show a => ShowDict a
+showDict = ShowDict { _showsPrec = showsPrec, _showList = showList }
+{-# INLINE showDict #-}
+
+instance (Reifies s (ShowDict a)) => Show (AdHoc s a) where
+  showsPrec = coerce $ _showsPrec (reflect (Proxy @s))
+  {-# INLINABLE showsPrec #-}
+
+  showList = coerce $ _showList (reflect (Proxy @s))
+  {-# INLINABLE showList #-}
+
+{-
+
+u/Iceland_jack taught me the technique to use QuantifiedConstraint on Coercible constraint. Thanks!
+
+https://www.reddit.com/r/haskell_jp/comments/a75z0s/blog_reflection%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF/ed3efcv/
+
+-}
+
+-- | Automatic Show1
+autoShow1 :: forall f b.
+     (forall a. Show a => Show (f a))
+  => (forall x y. Coercible x y => Coercible (f x) (f y))
+  => ShowDict b
+  -> ShowDict (f b)
+autoShow1 showB = reify showB body
+  where
+    body :: forall name. Reifies name (ShowDict b) => Proxy name -> ShowDict (f b)
+    body _ = coerce $ showDict @(f (AdHoc name b))
+{-# INLINABLE autoShow1 #-}
+
+-- | Automatic Show2
+autoShow2 :: forall f c d.
+     (forall a b. (Show a, Show b) => Show (f a b))
+  => (forall x1 x2 y1 y2.
+         (Coercible x1 y1, Coercible x2 y2) => Coercible (f x1 x2) (f y1 y2)
+       )
+  => ShowDict c
+  -> ShowDict d
+  -> ShowDict (f c d)
+autoShow2 showC showD =
+  reify showC $ \proxyC ->
+    reify showD $ \proxyD ->
+      body proxyC proxyD
+  where
+    body :: forall name1 name2. (Reifies name1 (ShowDict c), Reifies name2 (ShowDict d))
+         => Proxy name1 -> Proxy name2 -> ShowDict (f c d)
+    body _ _ = coerce $ showDict @(f (AdHoc name1 c) (AdHoc name2 d))
+{-# INLINABLE autoShow2 #-}
+
+-- * Read
+
+-- | Injected dictionary of 'Read'
+data ReadDict a = ReadDict
+  { _readPrec :: ReadPrec a
+  , _readListPrec :: ReadPrec [a]
+  }
+
+readDict :: forall a. Read a => ReadDict a
+readDict = ReadDict{ _readPrec = readPrec, _readListPrec = readListPrec }
+{-# INLINE readDict #-}
+
+instance (Reifies s (ReadDict a)) => Read (AdHoc s a) where
+  readPrec = coerce $ _readPrec (reflect (Proxy @s))
+  {-# INLINABLE readPrec #-}
+  readListPrec = coerce $ _readListPrec (reflect (Proxy @s))
+  {-# INLINABLE readListPrec #-}
+
+-- | Automatic Read1
+autoRead1 :: forall f b.
+     (forall a. Read a => Read (f a))
+  => (forall x y. Coercible x y => Coercible (f x) (f y))
+  => ReadDict b
+  -> ReadDict (f b)
+autoRead1 readB =
+  reify readB body
+  where
+    body :: forall name. (Reifies name (ReadDict b)) => Proxy name -> ReadDict (f b)
+    body _ = coerce (readDict @(f (AdHoc name b)))
+{-# INLINABLE autoRead1 #-}
+
+autoRead2 :: forall f c d.
+     (forall a b. (Read a, Read b) => Read (f a b))
+  => (forall x1 x2 y1 y2.
+         (Coercible x1 y1, Coercible x2 y2) => Coercible (f x1 x2) (f y1 y2)
+       )
+  => ReadDict c
+  -> ReadDict d
+  -> ReadDict (f c d)
+autoRead2 readC readD =
+  reify readC $ \proxyC ->
+    reify readD $ \proxyD ->
+      body proxyC proxyD
+  where
+    body :: forall name1 name2. (Reifies name1 (ReadDict c), Reifies name2 (ReadDict d))
+         => Proxy name1 -> Proxy name2 -> ReadDict (f c d)
+    body _ _ = coerce (readDict @(f (AdHoc name1 c) (AdHoc name2 d)))
+{-# INLINABLE autoRead2 #-}
