diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -27,4 +27,4 @@
 * Prefer generic functions
 * Debugging functions, like 'Intro.Trustworthy.trace' and 'undefined' are available but produce compile time warnings
 * Replace error with panic
-* Compatibility with unqualified import of Control.Lens
+* Compatibility with unqualified import of Control.Lens and Optics
diff --git a/intro.cabal b/intro.cabal
--- a/intro.cabal
+++ b/intro.cabal
@@ -1,13 +1,6 @@
 cabal-version: 1.12
-
--- This file has been generated from package.yaml by hpack version 0.31.2.
---
--- see: https://github.com/sol/hpack
---
--- hash: fe9a993c4dcd595f1858f7bb1fea002353d77bcdd733200b90049ea61a13c0a8
-
 name:           intro
-version:        0.6.0.1
+version:        0.7.0.0
 synopsis:       Safe and minimal prelude
 description:    Intro is a modern Prelude which provides safe alternatives
                 for most of the partial functions and follows other
@@ -29,7 +22,7 @@
 copyright:      2016-2017 Daniel Mendler
 license:        MIT
 license-file:   LICENSE
-tested-with:    GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.4
+tested-with:    GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.1
 build-type:     Simple
 extra-source-files:
     README.md
@@ -44,7 +37,6 @@
   other-modules:
       Intro.ConvertString
       Intro.Trustworthy
-      Paths_intro
   hs-source-dirs:
       src
   ghc-options: -Wall
@@ -54,7 +46,7 @@
     , containers >=0.5 && <0.7
     , deepseq >=1.4 && <1.5
     , dlist >=0.7 && <0.9
-    , extra >=1.5.1 && <1.7
+    , extra >=1.5.1 && <2.0
     , hashable >=1.2.5 && <2.0
     , mtl >=2.2 && <2.3
     , safe >=0.3.18 && <0.4
@@ -62,9 +54,6 @@
     , transformers >=0.4 && <0.6
     , unordered-containers >=0.2 && <0.3
     , writer-cps-mtl >=0.1.1.2 && <0.2
-  if impl(ghc < 8.1)
-    build-depends:
-        bifunctors >=5.2 && <5.5
   default-language: Haskell2010
 
 test-suite test
@@ -73,28 +62,26 @@
   other-modules:
       BaseCompat
       LensCompat
-      Paths_intro
+      OpticsCompat
   hs-source-dirs:
       test
   ghc-options: -Wall
   build-depends:
       QuickCheck
-    , base >=4.8 && <5.0
-    , bytestring >=0.9 && <0.11
-    , containers >=0.5 && <0.7
-    , deepseq >=1.4 && <1.5
-    , dlist >=0.7 && <0.9
-    , extra >=1.5.1 && <1.7
-    , hashable >=1.2.5 && <2.0
+    , base
+    , bytestring
+    , containers
+    , deepseq
+    , dlist
+    , extra
+    , hashable
     , intro
     , lens
-    , mtl >=2.2 && <2.3
-    , safe >=0.3.11 && <0.4
-    , text >=0.7 && <1.3
-    , transformers >=0.4 && <0.6
-    , unordered-containers >=0.2 && <0.3
-    , writer-cps-mtl >=0.1.1.2 && <0.2
-  if impl(ghc < 8.1)
-    build-depends:
-        bifunctors >=5.2 && <5.5
+    , optics
+    , mtl
+    , safe
+    , text
+    , transformers
+    , unordered-containers
+    , writer-cps-mtl
   default-language: Haskell2010
diff --git a/src/Intro.hs b/src/Intro.hs
--- a/src/Intro.hs
+++ b/src/Intro.hs
@@ -1,5 +1,4 @@
 {-# OPTIONS_HADDOCK show-extensions #-}
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
@@ -162,9 +161,7 @@
   , Data.List.isPrefixOf
   , Data.List.isSuffixOf
   , Data.List.iterate
-#if MIN_VERSION_base(4,11,0)
   , Data.List.iterate'
-#endif
   , Data.List.lookup
   , Data.List.Extra.nubOrd
   , Data.List.Extra.nubOrdBy
@@ -305,14 +302,6 @@
   , Prelude.Float
   , Prelude.Double
 
-  -- ** Rational
-  , Data.Ratio.Ratio
-  , Data.Ratio.Rational
-  , (Data.Ratio.%)
-  , Data.Ratio.numerator
-  , Data.Ratio.denominator
-  , Data.Ratio.approxRational
-
   -- * Numeric type classes
 
   -- ** Num
@@ -362,37 +351,29 @@
 
   -- ** Show
   , Text.Show.Show
-#if MIN_VERSION_base(4,9,0)
   , Data.Functor.Classes.Show1
   , Data.Functor.Classes.Show2
-#endif
   , show
   , showT
   , showS
 
   -- ** Read
   , Text.Read.Read
-#if MIN_VERSION_base(4,9,0)
   , Data.Functor.Classes.Read1
   , Data.Functor.Classes.Read2
-#endif
   , readMaybe
 
   -- * Equality and ordering
 
   -- ** Eq
   , Data.Eq.Eq((==), (/=))
-#if MIN_VERSION_base(4,9,0)
   , Data.Functor.Classes.Eq1
   , Data.Functor.Classes.Eq2
-#endif
 
   -- ** Ord
   , Data.Ord.Ord(compare, (<), (>), (<=), (>=), max, min)
-#if MIN_VERSION_base(4,9,0)
   , Data.Functor.Classes.Ord1
   , Data.Functor.Classes.Ord2
-#endif
   , Data.Ord.Ordering(LT,GT,EQ)
   , Data.Ord.Down(Down)
   , Data.Ord.comparing
@@ -447,9 +428,7 @@
       )
   , (Data.Functor.$>)
   , (Data.Functor.<$>)
-#if MIN_VERSION_base(4,11,0)
   , (Data.Functor.<&>)
-#endif
   , map
   , Data.Functor.void
   , Control.Applicative.Const(Const, getConst) -- Data.Functor.Const
@@ -630,15 +609,11 @@
   , GHC.Generics.Generic1
   , Data.Typeable.Typeable
   , Control.DeepSeq.NFData
-#if MIN_VERSION_base(4,10,0)
   , Control.DeepSeq.NFData1
   , Control.DeepSeq.NFData2
-#endif
 
   -- * Type level
-#if MIN_VERSION_base(4,9,0)
   , Data.Kind.Type
-#endif
   , Intro.Trustworthy.Constraint
   , Data.Proxy.Proxy(Proxy)
   --, Data.Tagged.Tagged(Tagged)
@@ -666,9 +641,7 @@
 
   -- * Error handling and debugging
   , HasCallStack
-#if MIN_VERSION_base(4,9,0)
   , Control.Monad.Fail.MonadFail
-#endif
   , fail
   , panic
   , undefined
@@ -700,6 +673,7 @@
 import qualified Control.Monad
 import qualified Control.Monad.Except
 import qualified Control.Monad.Extra
+import qualified Control.Monad.Fail
 import qualified Control.Monad.Fix
 import qualified Control.Monad.RWS.CPS
 import qualified Control.Monad.Reader
@@ -721,6 +695,7 @@
 import qualified Data.Foldable
 import qualified Data.Function
 import qualified Data.Functor
+import qualified Data.Functor.Classes
 import qualified Data.Functor.Identity
 import qualified Data.HashMap.Strict
 import qualified Data.HashSet
@@ -728,6 +703,7 @@
 import qualified Data.Int
 import qualified Data.IntMap
 import qualified Data.IntSet
+import qualified Data.Kind
 import qualified Data.List
 import qualified Data.List.Extra
 import qualified Data.List.NonEmpty
@@ -736,7 +712,6 @@
 import qualified Data.Monoid
 import qualified Data.Ord
 import qualified Data.Proxy
-import qualified Data.Ratio
 import qualified Data.Semigroup
 import qualified Data.Sequence
 import qualified Data.Set
@@ -756,12 +731,6 @@
 import qualified Text.Read
 import qualified Text.Show
 
-#if MIN_VERSION_base(4,9,0)
-import qualified Control.Monad.Fail
-import qualified Data.Functor.Classes
-import qualified Data.Kind
-#endif
-
 -- | Alias for lazy 'Data.Text.Lazy.Text'
 type LText = Data.Text.Lazy.Text
 
@@ -955,11 +924,6 @@
 -- @
 -- fail _ = mzero
 -- @
-#if MIN_VERSION_base(4,9,0)
 fail :: Control.Monad.Fail.MonadFail m => Text -> m a
 fail = Control.Monad.Fail.fail . convertString
-#else
-fail :: Control.Monad.Monad m => Text -> m a
-fail = Control.Monad.fail . convertString
-#endif
 {-# INLINE fail #-}
diff --git a/src/Intro/Trustworthy.hs b/src/Intro/Trustworthy.hs
--- a/src/Intro/Trustworthy.hs
+++ b/src/Intro/Trustworthy.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE NoImplicitPrelude #-}
@@ -46,18 +45,9 @@
 import qualified Debug.Trace
 import qualified GHC.Exts
 import qualified Data.Hashable.Lifted
-
-#if MIN_VERSION_base(4,9,0)
 import Control.Applicative (Applicative)
 import Data.Kind (Constraint)
 import GHC.Stack (HasCallStack)
-#define APPLICATIVE Applicative
-#else
-import Control.Monad (Monad)
-import GHC.Exts (Constraint)
-type HasCallStack = (() :: GHC.Exts.Constraint)
-#define APPLICATIVE Monad
-#endif
 
 -- | The 'trace' function outputs the trace message given as its first argument,
 -- before returning the second argument as its result.
@@ -89,7 +79,7 @@
 -- >   traceM $ "x: " ++ show x
 -- >   y <- ...
 -- >   traceM $ "y: " ++ show y
-traceM :: APPLICATIVE m => Text -> m ()
+traceM :: Applicative m => Text -> m ()
 traceM = Debug.Trace.traceM . unpack
 {-# WARNING traceM "'traceM' should be used only for debugging" #-}
 
@@ -115,7 +105,7 @@
 -- >   traceShowM $ x
 -- >   y <- ...
 -- >   traceShowM $ x + y
-traceShowM :: (Show a, APPLICATIVE m) => a -> m ()
+traceShowM :: (Show a, Applicative m) => a -> m ()
 traceShowM = Debug.Trace.traceShowM
 {-# WARNING traceShowM "'traceShowM' should be used only for debugging" #-}
 
diff --git a/test/BaseCompat.hs b/test/BaseCompat.hs
--- a/test/BaseCompat.hs
+++ b/test/BaseCompat.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE CPP #-}
 module BaseCompat (
   module X
 ) where
@@ -77,8 +76,5 @@
 import Text.Read as X hiding (readMaybe, get, lift, EOF, (+++))
 import Text.Show as X hiding (show)
 import Unsafe.Coerce as X
-
-#if MIN_VERSION_base(4,9,0)
 import Control.Monad.Fail as X hiding (fail)
 import Data.Kind as X
-#endif
diff --git a/test/OpticsCompat.hs b/test/OpticsCompat.hs
new file mode 100644
--- /dev/null
+++ b/test/OpticsCompat.hs
@@ -0,0 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module OpticsCompat (
+  module X
+) where
+
+import Intro as X
+import Optics as X
diff --git a/test/test.hs b/test/test.hs
--- a/test/test.hs
+++ b/test/test.hs
@@ -9,6 +9,7 @@
 import Data.ByteString.Short (ShortByteString)
 import Intro
 import LensCompat ()
+import OpticsCompat ()
 import Test.QuickCheck
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as LB
