diff --git a/ASCII/Case.hs b/ASCII/Case.hs
new file mode 100644
--- /dev/null
+++ b/ASCII/Case.hs
@@ -0,0 +1,112 @@
+{- |
+
+/Case/ is a property of letters. /A-Z/ are /upper case/ letters, and /a-z/ are /lower case/ letters. No other ASCII characters have case.
+
+-}
+
+module ASCII.Case ( Case (..), letterCase, isCase, toCase ) where
+
+import ASCII.Char    ( Char (..) )
+import Data.Bool     ( Bool, otherwise )
+import Data.Data     ( Data )
+import Data.Eq       ( Eq )
+import Data.Function ( (.), ($) )
+import Data.Hashable ( Hashable )
+import Data.Ord      ( Ord, (<=), (>=) )
+import GHC.Generics  ( Generic )
+import Prelude       ( Enum, Bounded, Int, (+), (-) )
+import Text.Show     ( Show )
+import Data.Maybe    ( Maybe (..) )
+
+import qualified ASCII.Char as Char
+import qualified Data.Bool  as Bool
+
+{- $setup
+
+>>> import Prelude
+
+-}
+
+data Case =
+    UpperCase -- ^ The letters from 'CapitalLetterA' to 'CapitalLetterZ'.
+  | LowerCase -- ^ The letters from 'SmallLetterA' to 'SmallLetterZ'.
+
+deriving stock instance Eq Case
+
+deriving stock instance Ord Case
+
+deriving stock instance Enum Case
+
+deriving stock instance Bounded Case
+
+deriving stock instance Show Case
+
+deriving stock instance Data Case
+
+deriving stock instance Generic Case
+
+deriving anyclass instance Hashable Case
+
+{- | Determines whether a character is a letter, and if so, whether it is upper or lower case.
+
+>>> map letterCase [CapitalLetterR, SmallLetterR, DollarSign]
+[Just UpperCase,Just LowerCase,Nothing]
+
+-}
+
+letterCase :: Char -> Maybe Case
+letterCase x | isCase UpperCase x = Just UpperCase
+             | isCase LowerCase x = Just LowerCase
+             | otherwise          = Nothing
+
+{- | Determines whether a character is a letter of a particular case.
+
+>>> map (isCase UpperCase) [CapitalLetterR,SmallLetterR,DollarSign]
+[True,False,False]
+
+-}
+
+isCase :: Case -> Char -> Bool
+isCase c x = (Bool.&&) ( x >= a ) ( x <= z ) where (a, z) = az c
+
+az :: Case -> (Char, Char)
+az UpperCase = (CapitalLetterA, CapitalLetterZ)
+az LowerCase = (SmallLetterA, SmallLetterZ)
+
+{- | Maps a letter character to its upper/lower case equivalent.
+
+>>> toCase UpperCase SmallLetterX
+CapitalLetterX
+
+>>> toCase LowerCase CapitalLetterF
+SmallLetterF
+
+Characters that are already in the requested case are unmodified by this transformation.
+
+>>> toCase UpperCase CapitalLetterA
+CapitalLetterA
+
+Characters that are not letters, such as exclamation mark, are unmodified by this transformation.
+
+>>> toCase UpperCase ExclamationMark
+ExclamationMark
+
+-}
+
+toCase :: Case -> Char -> Char
+toCase c x = if isCase (opposite c) x then changeCaseUnsafe c x else x
+
+-- | Change a letter to the given case, assuming that the input character is a letter of the opposite case.
+
+changeCaseUnsafe :: Case -> Char -> Char
+changeCaseUnsafe c = charAsIntUnsafe (changeCaseInt c)
+
+changeCaseInt :: Case -> Int -> Int
+changeCaseInt LowerCase i = i + 32
+changeCaseInt UpperCase i = i - 32
+
+opposite UpperCase = LowerCase
+opposite LowerCase = UpperCase
+
+charAsIntUnsafe :: (Int -> Int) -> (Char -> Char)
+charAsIntUnsafe f = Char.fromIntUnsafe . f . Char.toInt
diff --git a/ascii-case.cabal b/ascii-case.cabal
new file mode 100644
--- /dev/null
+++ b/ascii-case.cabal
@@ -0,0 +1,41 @@
+cabal-version: 2.0
+
+name: ascii-case
+version: 1.0.0.0
+synopsis: ASCII letter case
+category: Data, Text
+
+description: This package defines a @Case@ type that describes the two varieties of ASCII letter: capital and small.
+
+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: StandaloneDeriving
+    default-extensions: DerivingStrategies
+    default-extensions: DeriveAnyClass
+    default-extensions: DeriveDataTypeable
+    default-extensions: DeriveGeneric
+    ghc-options: -Wall
+
+    build-depends: ascii-char >= 1.0  && < 1.1
+    build-depends: base       >= 4.11 && < 4.14
+    build-depends: hashable   >= 1.2  && < 1.4
+
+    exposed-modules: ASCII.Case
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.
