diff --git a/ASCII/Char.hs b/ASCII/Char.hs
new file mode 100644
--- /dev/null
+++ b/ASCII/Char.hs
@@ -0,0 +1,131 @@
+{- |
+
+The 'Char' type has 128 nullary constructors, listed in order according to each character's 7-bit numeric code.
+
+-}
+
+module ASCII.Char
+  (
+    {- * The @Char@ type -} Char (..),
+    {- * Conversions with @Int@ -} toInt, fromIntMaybe, fromIntUnsafe,
+    {- * Enumeration -} allCharacters
+    {- * Notes -} {- $notes -}
+  )
+  where
+
+import Data.Bool     ( otherwise )
+import Data.Data     ( Data )
+import Data.Eq       ( Eq )
+import Data.Ord      ( Ord, (<), (>) )
+import Data.Hashable ( Hashable )
+import Data.Int      ( Int )
+import Data.Maybe    ( Maybe (..) )
+import Prelude       ( Enum, enumFromTo, toEnum, fromEnum,
+                       Bounded, minBound, maxBound )
+import Text.Show     ( Show )
+import GHC.Generics  ( Generic )
+
+{- $setup
+
+>>> import Prelude hiding (Char)
+
+-}
+
+-- | A character in the ASCII character set.
+
+data Char =
+      Null | StartOfHeading | StartOfText | EndOfText | EndOfTransmission | Enquiry | Acknowledgement | Bell | Backspace | HorizontalTab | LineFeed | VerticalTab | FormFeed | CarriageReturn | ShiftOut | ShiftIn | DataLinkEscape
+
+    | DeviceControl1 | DeviceControl2 | DeviceControl3 | DeviceControl4
+
+    | NegativeAcknowledgement | SynchronousIdle | EndOfTransmissionBlock | Cancel | EndOfMedium | Substitute | Escape
+
+    | FileSeparator | GroupSeparator | RecordSeparator | UnitSeparator
+
+    | Space | ExclamationMark | QuotationMark | NumberSign | DollarSign | PercentSign | Ampersand | Apostrophe | LeftParenthesis | RightParenthesis | Asterisk | PlusSign | Comma | HyphenMinus | FullStop | Slash
+
+    | Digit0 | Digit1 | Digit2 | Digit3 | Digit4 | Digit5 | Digit6 | Digit7 | Digit8 | Digit9
+
+    | Colon | Semicolon | LessThanSign | EqualsSign | GreaterThanSign | QuestionMark | AtSign
+
+    | CapitalLetterA | CapitalLetterB | CapitalLetterC | CapitalLetterD | CapitalLetterE | CapitalLetterF | CapitalLetterG | CapitalLetterH | CapitalLetterI | CapitalLetterJ | CapitalLetterK | CapitalLetterL | CapitalLetterM | CapitalLetterN | CapitalLetterO | CapitalLetterP | CapitalLetterQ | CapitalLetterR | CapitalLetterS | CapitalLetterT | CapitalLetterU | CapitalLetterV | CapitalLetterW | CapitalLetterX | CapitalLetterY | CapitalLetterZ
+
+    | LeftSquareBracket | Backslash | RightSquareBracket | Caret | Underscore | GraveAccent
+
+    | SmallLetterA | SmallLetterB | SmallLetterC | SmallLetterD | SmallLetterE | SmallLetterF | SmallLetterG | SmallLetterH | SmallLetterI | SmallLetterJ | SmallLetterK | SmallLetterL | SmallLetterM | SmallLetterN | SmallLetterO | SmallLetterP | SmallLetterQ | SmallLetterR | SmallLetterS | SmallLetterT | SmallLetterU | SmallLetterV | SmallLetterW | SmallLetterX | SmallLetterY | SmallLetterZ
+
+    | LeftCurlyBracket | VerticalLine | RightCurlyBracket | Tilde | Delete
+
+deriving stock instance Eq Char
+
+deriving stock instance Ord Char
+
+-- | Instead of @Enum@ methods, consider using 'toInt' and 'fromIntMaybe'.
+deriving stock instance Enum Char
+
+-- | The least character is 'Null', and the greatest character is 'Delete'.
+deriving stock instance Bounded Char
+
+deriving stock instance Show Char
+
+deriving stock instance Data Char
+
+deriving stock instance Generic Char
+
+deriving anyclass instance Hashable Char
+
+{- | Converts an ASCII character to its corresponding numeric value between 0 and 127.
+
+>>> map toInt [Null, CapitalLetterA, SmallLetterA, Delete]
+[0,65,97,127]
+
+-}
+
+toInt :: Char -> Int
+toInt = Prelude.fromEnum
+
+{- | Returns 'Just' the ASCII character corresponding to a numeric value between 0 and 127, or 'Nothing' for numbers outside this range.
+
+>>> map fromIntMaybe [-1, 0, 65, 127, 128]
+[Nothing,Just Null,Just CapitalLetterA,Just Delete,Nothing]
+
+-}
+
+fromIntMaybe :: Int -> Maybe Char
+fromIntMaybe x | x < 0     = Nothing
+               | x > 127   = Nothing
+               | otherwise = Just (fromIntUnsafe x)
+
+{- | The inverse of 'toInt'.
+
+This is marked as /unsafe/ because it is undefined for numbers below 0 or above 127. The safe variant of this function is 'fromIntMaybe'.
+
+>>> map fromIntUnsafe [65, 66, 67]
+[CapitalLetterA,CapitalLetterB,CapitalLetterC]
+
+-}
+
+fromIntUnsafe :: Int -> Char
+fromIntUnsafe = Prelude.toEnum
+
+allCharacters :: [Char]
+allCharacters = Prelude.enumFromTo Prelude.minBound Prelude.maxBound
+
+{- $notes
+
+There are 128 characters in total.
+
+>>> length allCharacters
+128
+
+Null is the first character.
+
+>>> minBound :: Char
+Null
+
+Delete is the last character.
+
+>>> maxBound :: Char
+Delete
+
+-}
diff --git a/ascii-char.cabal b/ascii-char.cabal
new file mode 100644
--- /dev/null
+++ b/ascii-char.cabal
@@ -0,0 +1,40 @@
+cabal-version: 2.0
+
+name: ascii-char
+version: 1.0.0.0
+synopsis: A Char type representing an ASCII character
+category: Data, Text
+
+description: This package defines a @Char@ type that has 128 constructors, one for each ASCII character.
+
+license: Apache-2.0
+license-file: license.txt
+
+author: Chris Martin
+maintainer: Chris Martin, Julie Moronuki
+
+homepage:    https://github.com/typeclasses/ascii
+bug-Reports: https://github.com/typeclasses/ascii/issues
+
+build-type: Simple
+
+tested-with: GHC == 8.8.1, GHC == 8.6.5, GHC == 8.4.3
+
+source-repository head
+    type:     git
+    location: git://github.com/typeclasses/ascii.git
+
+library
+    default-language: Haskell2010
+    default-extensions: NoImplicitPrelude
+    default-extensions: DeriveAnyClass
+    default-extensions: DeriveDataTypeable
+    default-extensions: DeriveGeneric
+    default-extensions: StandaloneDeriving
+    default-extensions: DerivingStrategies
+    ghc-options: -Wall
+
+    build-depends: base     >= 4.11 && < 4.14
+    build-depends: hashable >= 1.2  && < 1.4
+
+    exposed-modules: ASCII.Char
diff --git a/license.txt b/license.txt
new file mode 100644
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,13 @@
+Copyright 2020 Typeclass Consulting LLC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
