diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for union-color
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Yoshikuni Jujo (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 Yoshikuni Jujo 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,1 @@
+# union-color
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/src/Data/Color.hs b/src/Data/Color.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Color.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE PatternSynonyms #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.Color (
+	-- * Alpha
+	Alpha, pattern AlphaWord8, pattern AlphaWord16, pattern AlphaDouble,
+	alphaDouble, alphaRealToFrac,
+	-- * RGB
+	Rgb, pattern RgbWord8, pattern RgbWord16, pattern RgbDouble,
+	rgbDouble, rgbRealToFrac,
+	-- * RGBA
+	-- ** Straight
+	Rgba, pattern RgbaWord8, pattern RgbaWord16, pattern RgbaDouble,
+	rgbaDouble,
+	-- ** Premultiplied
+	pattern RgbaPremultipliedWord8, rgbaPremultipliedWord8,
+	pattern RgbaPremultipliedWord16, rgbaPremultipliedWord16,
+	pattern RgbaPremultipliedDouble, rgbaPremultipliedDouble,
+	-- ** From and To Rgb and Alpha
+	toRgba, fromRgba,
+	-- ** Convert Fractional
+	rgbaRealToFrac ) where
+
+import Data.Color.Internal
diff --git a/src/Data/Color/Internal.hs b/src/Data/Color/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Color/Internal.hs
@@ -0,0 +1,362 @@
+{-# LANGUAGE LambdaCase, ViewPatterns #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.Color.Internal (
+	-- * Alpha
+	Alpha(..), pattern AlphaWord8, pattern AlphaWord16, pattern AlphaDouble,
+	alphaDouble, alphaRealToFrac,
+	-- * RGB
+	Rgb(..), pattern RgbWord8, pattern RgbWord16, pattern RgbDouble,
+	rgbDouble, rgbRealToFrac,
+	-- * RGBA
+	-- ** Straight
+	Rgba(..), pattern RgbaWord8, pattern RgbaWord16, pattern RgbaDouble,
+	rgbaDouble,
+	-- ** Premultiplied
+	pattern RgbaPremultipliedWord8, rgbaPremultipliedWord8,
+	pattern RgbaPremultipliedWord16, rgbaPremultipliedWord16,
+	pattern RgbaPremultipliedDouble, rgbaPremultipliedDouble,
+	-- ** From and To Rgb and Alpha
+	toRgba, fromRgba,
+	-- ** Convert Fractional
+	rgbaRealToFrac ) where
+
+import Data.Bits
+import Data.Word
+
+data Alpha d = AlphaWord8_ Word8 | AlphaWord16_ Word16 | AlphaDouble_ d
+	deriving Show
+
+{-# COMPLETE AlphaWord8 #-}
+
+pattern AlphaWord8 :: RealFrac d => Word8 -> Alpha d
+pattern AlphaWord8 a <- (fromAlphaWord8 -> a)
+	where AlphaWord8 = AlphaWord8_
+
+fromAlphaWord8 :: RealFrac d => Alpha d -> Word8
+fromAlphaWord8 = \case
+	AlphaWord8_ a -> a
+	AlphaWord16_ a -> fromIntegral $ a `shiftR` 8
+	AlphaDouble_ a -> cDoubleToWord8 a
+
+{-# COMPLETE AlphaWord16 #-}
+
+pattern AlphaWord16 :: RealFrac d => Word16 -> Alpha d
+pattern AlphaWord16 a <- (fromAlphaWord16 -> a)
+	where AlphaWord16 = AlphaWord16_
+
+fromAlphaWord16 :: RealFrac d => Alpha d -> Word16
+fromAlphaWord16 = \case
+	AlphaWord8_ (fromIntegral -> a) -> a `shiftL` 8 .|. a
+	AlphaWord16_ a -> a
+	AlphaDouble_ a -> cDoubleToWord16 a
+
+{-# COMPLETE AlphaDouble #-}
+
+pattern AlphaDouble :: Fractional d => d -> (Alpha d)
+pattern AlphaDouble a <- (fromAlphaDouble -> a)
+
+fromAlphaDouble :: Fractional d => Alpha d -> d
+fromAlphaDouble = \case
+	AlphaWord8_ a -> word8ToCDouble a
+	AlphaWord16_ a -> word16ToCDouble a
+	AlphaDouble_ a -> a
+
+alphaDouble :: (Ord d, Num d) => d -> Maybe (Alpha d)
+alphaDouble a
+	| from0to1 a = Just $ AlphaDouble_ a
+	| otherwise = Nothing
+
+alphaRealToFrac :: (Real d, Fractional d') => Alpha d -> Alpha d'
+alphaRealToFrac = \case
+	AlphaWord8_ a -> AlphaWord8_ a
+	AlphaWord16_ a -> AlphaWord16_ a
+	AlphaDouble_ a -> AlphaDouble_ $ realToFrac a
+
+data Rgb d
+	= RgbWord8_ Word8 Word8 Word8
+	| RgbWord16_ Word16 Word16 Word16
+	| RgbDouble_ d d d
+	deriving Show
+
+{-# COMPLETE RgbWord8 #-}
+
+pattern RgbWord8 :: RealFrac d => Word8 -> Word8 -> Word8 -> Rgb d
+pattern RgbWord8 r g b <- (fromRgbWord8 -> (r, g, b))
+	where RgbWord8 = RgbWord8_
+
+fromRgbWord8 :: RealFrac d => Rgb d -> (Word8, Word8, Word8)
+fromRgbWord8 = \case
+	RgbWord8_ r g b -> (r, g, b)
+	RgbWord16_ r g b -> (
+		fromIntegral $ r `shiftR` 8,
+		fromIntegral $ g `shiftR` 8,
+		fromIntegral $ b `shiftR` 8 )
+	RgbDouble_ r g b ->
+		let [r', g', b'] = cDoubleToWord8 <$> [r, g, b] in (r', g', b')
+
+{-# COMPLETE RgbWord16 #-}
+
+pattern RgbWord16 :: RealFrac d => Word16 -> Word16 -> Word16 -> Rgb d
+pattern RgbWord16 r g b <- (fromRgbWord16 -> (r, g, b))
+	where RgbWord16 = RgbWord16_
+
+fromRgbWord16 :: RealFrac d => Rgb d -> (Word16, Word16, Word16)
+fromRgbWord16 = \case
+	RgbWord8_ (fromIntegral -> r) (fromIntegral -> g) (fromIntegral -> b) ->
+		(r `shiftL` 8 .|. r, g `shiftL` 8 .|. g, b `shiftL` 8 .|. b)
+	RgbWord16_ r g b -> (r, g, b)
+	RgbDouble_ r g b ->
+		let [r', g', b'] = cDoubleToWord16 <$> [r, g, b] in (r', g', b')
+
+{-# COMPLETE RgbDouble #-}
+
+pattern RgbDouble :: Fractional d => d -> d -> d -> (Rgb d)
+pattern RgbDouble r g b <- (fromRgbDouble -> (r, g, b))
+
+fromRgbDouble :: Fractional d => Rgb d -> (d, d, d)
+fromRgbDouble = \case
+	RgbWord8_ r g b ->
+		let [r', g', b'] = word8ToCDouble <$> [r, g, b] in (r', g', b')
+	RgbWord16_ r g b ->
+		let [r', g', b'] = word16ToCDouble <$> [r, g, b] in (r', g', b')
+	RgbDouble_ r g b -> (r, g, b)
+
+rgbDouble :: (Ord d, Num d) => d -> d -> d -> Maybe (Rgb d)
+rgbDouble r g b
+	| from0to1 r && from0to1 g && from0to1 b = Just $ RgbDouble_ r g b
+	| otherwise = Nothing
+
+rgbRealToFrac :: (Real d, Fractional d') => Rgb d -> Rgb d'
+rgbRealToFrac = \case
+	RgbWord8_ r g b -> RgbWord8_ r g b
+	RgbWord16_ r g b -> RgbWord16_ r g b
+	RgbDouble_ r g b -> RgbDouble_ r' g' b'
+		where [r', g', b'] = realToFrac <$> [r, g, b]
+
+data Rgba d
+	= RgbaWord8_ Word8 Word8 Word8 Word8
+	| RgbaWord16_ Word16 Word16 Word16 Word16
+	| RgbaDouble_ d d d d
+	| RgbaPremultipliedWord8_ Word8 Word8 Word8 Word8
+	| RgbaPremultipliedWord16_ Word16 Word16 Word16 Word16
+	| RgbaPremultipliedDouble_ d d d d
+	deriving Show
+
+{-# COMPLETE RgbaWord8 #-}
+
+pattern RgbaWord8 :: RealFrac d => Word8 -> Word8 -> Word8 -> Word8 -> Rgba d
+pattern RgbaWord8 r g b a <- (fromRgbaWord8 -> (r, g, b, a))
+	where RgbaWord8 = RgbaWord8_
+
+fromRgbaWord8 :: RealFrac d => Rgba d -> (Word8, Word8, Word8, Word8)
+fromRgbaWord8 = \case
+	RgbaWord8_ r g b a -> (r, g, b, a)
+	RgbaWord16_ r g b a -> (
+		fromIntegral $ r `shiftR` 8,
+		fromIntegral $ g `shiftR` 8,
+		fromIntegral $ b `shiftR` 8,
+		fromIntegral $ a `shiftR` 8 )
+	RgbaDouble_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] = cDoubleToWord8 <$> [r, g, b, a]
+	RgbaPremultipliedWord8_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] = unPremultipliedWord8 (r, g, b, a)
+	RgbaPremultipliedWord16_ r g b a -> (
+		fromIntegral $ r' `shiftR` 8,
+		fromIntegral $ g' `shiftR` 8,
+		fromIntegral $ b' `shiftR` 8,
+		fromIntegral $ a' `shiftR` 8 )
+		where [r', g', b', a'] = unPremultipliedWord16 (r, g, b, a)
+	RgbaPremultipliedDouble_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] =
+			cDoubleToWord8 <$> unPremultipliedDouble (r, g, b, a)
+
+{-# COMPLETE RgbaWord16 #-}
+
+pattern RgbaWord16 :: RealFrac d => Word16 -> Word16 -> Word16 -> Word16 -> Rgba d
+pattern RgbaWord16 r g b a <- (fromRgbaWord16 -> (r, g, b, a))
+	where RgbaWord16 = RgbaWord16_
+
+fromRgbaWord16 :: RealFrac d => Rgba d -> (Word16, Word16, Word16, Word16)
+fromRgbaWord16 = \case
+	RgbaWord8_
+		(fromIntegral -> r) (fromIntegral -> g)
+		(fromIntegral -> b) (fromIntegral -> a) -> (
+		r `shiftL` 8 .|. r, g `shiftL` 8 .|. g,
+		b `shiftL` 8 .|. b, a `shiftL` 8 .|. a)
+	RgbaWord16_ r g b a -> (r, g, b, a)
+	RgbaDouble_ r g b a ->
+		let [r', g', b', a'] = cDoubleToWord16 <$> [r, g, b, a] in (r', g', b', a')
+	RgbaPremultipliedWord8_ r g b a -> (
+		r' `shiftL` 8 .|. r', g' `shiftL` 8 .|. g',
+		b' `shiftL` 8 .|. b', a' `shiftL` 8 .|. a')
+		where [r', g', b', a'] =
+			fromIntegral <$> unPremultipliedWord8 (r, g, b, a)
+	RgbaPremultipliedWord16_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] = unPremultipliedWord16 (r, g, b, a)
+	RgbaPremultipliedDouble_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] =
+			cDoubleToWord16 <$> unPremultipliedDouble (r, g, b, a)
+
+{-# COMPLETE RgbaDouble #-}
+
+pattern RgbaDouble :: (Eq d, Fractional d) => d -> d -> d -> d -> Rgba d
+pattern RgbaDouble r g b a <- (fromRgbaDouble -> (r, g, b, a))
+
+fromRgbaDouble :: (Eq d, Fractional d) => Rgba d -> (d, d, d, d)
+fromRgbaDouble = \case
+	RgbaWord8_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] = word8ToCDouble <$> [r, g, b, a]
+	RgbaWord16_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] = word16ToCDouble <$> [r, g, b, a]
+	RgbaDouble_ r g b a -> (r, g, b, a)
+	RgbaPremultipliedWord8_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] =
+			word8ToCDouble <$> unPremultipliedWord8 (r, g, b, a)
+	RgbaPremultipliedWord16_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] =
+			word16ToCDouble <$> unPremultipliedWord16 (r, g, b, a)
+	RgbaPremultipliedDouble_ r g b a -> (r', g', b', a')
+		where [r', g', b', a'] = unPremultipliedDouble (r, g, b, a)
+
+rgbaDouble :: (Ord d, Num d) => d -> d -> d -> d -> Maybe (Rgba d)
+rgbaDouble r g b a
+	| from0to1 r && from0to1 g && from0to1 b && from0to1 a =
+		Just $ RgbaDouble_ r g b a
+	| otherwise = Nothing
+
+fromRgba :: (Eq d, Fractional d) => Rgba d -> (Rgb d, Alpha d)
+fromRgba = \case
+	RgbaWord8_ r g b a -> (RgbWord8_ r g b, AlphaWord8_ a)
+	RgbaWord16_ r g b a -> (RgbWord16_ r g b, AlphaWord16_ a)
+	RgbaDouble_ r g b a -> (RgbDouble_ r g b, AlphaDouble_ a)
+	RgbaPremultipliedWord8_ r g b a -> (RgbWord8_ r' g' b', AlphaWord8_ a')
+		where [r', g', b', a'] = unPremultipliedWord8 (r, g, b, a)
+	RgbaPremultipliedWord16_ r g b a -> (RgbWord16_ r' g' b', AlphaWord16_ a')
+		where [r', g', b', a'] = unPremultipliedWord16 (r, g, b, a)
+	RgbaPremultipliedDouble_ r g b a -> (RgbDouble_ r' g' b', AlphaDouble_ a')
+		where [r', g', b', a'] = unPremultipliedDouble (r, g, b, a)
+
+toRgba :: RealFrac d => Rgb d -> Alpha d -> Rgba d
+toRgba (RgbWord8_ r g b) (AlphaWord8 a) = RgbaWord8 r g b a
+toRgba (RgbWord16_ r g b) (AlphaWord16 a) = RgbaWord16 r g b a
+toRgba (RgbDouble_ r g b) (AlphaDouble a) = RgbaDouble_ r g b a
+
+rgbaRealToFrac :: (Real d, Fractional d') => Rgba d -> Rgba d'
+rgbaRealToFrac = \case
+	RgbaWord8_ r g b a -> RgbaWord8_ r g b a
+	RgbaWord16_ r g b a -> RgbaWord16_ r g b a
+	RgbaDouble_ r g b a -> RgbaDouble_ r' g' b' a'
+		where [r', g', b', a'] = realToFrac <$> [r, g, b, a]
+	RgbaPremultipliedWord8_ r g b a -> RgbaPremultipliedWord8_ r g b a
+	RgbaPremultipliedWord16_ r g b a -> RgbaPremultipliedWord16_ r g b a
+	RgbaPremultipliedDouble_ r g b a -> RgbaPremultipliedDouble_ r' g' b' a'
+		where [r', g', b', a'] = realToFrac <$> [r, g, b, a]
+
+cDoubleToWord8 :: RealFrac d => d -> Word8
+cDoubleToWord8 = round . (* 0xff)
+
+cDoubleToWord16 :: RealFrac d => d -> Word16
+cDoubleToWord16 = round . (* 0xffff)
+
+word8ToCDouble :: Fractional d => Word8 -> d
+word8ToCDouble = (/ 0xff) . fromIntegral
+
+word16ToCDouble :: Fractional d => Word16 -> d
+word16ToCDouble = (/ 0xffff) . fromIntegral
+
+from0to1 :: (Ord d, Num d) => d -> Bool
+from0to1 n = 0 <= n && n <= 1
+
+{-# COMPLETE RgbaPremultipliedWord8 #-}
+
+pattern RgbaPremultipliedWord8 ::
+	RealFrac d => Word8 -> Word8 -> Word8 -> Word8 -> Rgba d
+pattern RgbaPremultipliedWord8 r g b a <-
+	(fromRgbaPremultipliedWord8 -> (r, g, b, a))
+
+rgbaPremultipliedWord8 :: Word8 -> Word8 -> Word8 -> Word8 -> Maybe (Rgba d)
+rgbaPremultipliedWord8 r g b a
+	| r <= a && g <= a && b <= a = Just $ RgbaPremultipliedWord8_ r g b a
+	| otherwise = Nothing
+
+fromRgbaPremultipliedWord8 :: RealFrac d => Rgba d -> (Word8, Word8, Word8, Word8)
+fromRgbaPremultipliedWord8 = toPremultipliedWord8 . fromRgbaWord8
+
+toPremultipliedWord8 ::
+	(Word8, Word8, Word8, Word8) -> (Word8, Word8, Word8, Word8)
+toPremultipliedWord8 (
+	fromIntegral -> r, fromIntegral -> g,
+	fromIntegral -> b, fromIntegral -> a) = (r', g', b', a')
+	where
+	[r', g', b', a'] = fromIntegral <$> [
+		r * a `div` 0xff, g * a `div` 0xff, b * a `div` 0xff,
+		a :: Word16 ]
+
+unPremultipliedWord8 :: (Word8, Word8, Word8, Word8) -> [Word8]
+unPremultipliedWord8 (
+	fromIntegral -> r, fromIntegral -> g,
+	fromIntegral -> b, fromIntegral -> a ) = fromIntegral <$> [
+		r * 0xff `div'` a, g * 0xff `div'` a, b * 0xff `div'` a,
+		a :: Word16 ]
+
+{-# COMPLETE RgbaPremultipliedWord16 #-}
+
+pattern RgbaPremultipliedWord16 ::
+	RealFrac d => Word16 -> Word16 -> Word16 -> Word16 -> Rgba d
+pattern RgbaPremultipliedWord16 r g b a <-
+	(fromRgbaPremultipliedWord16 -> (r, g, b, a))
+
+rgbaPremultipliedWord16 :: Word16 -> Word16 -> Word16 -> Word16 -> Maybe (Rgba d)
+rgbaPremultipliedWord16 r g b a
+	| r <= a && g <= a && b <= a = Just $ RgbaPremultipliedWord16_ r g b a
+	| otherwise = Nothing
+
+fromRgbaPremultipliedWord16 ::
+	RealFrac d => Rgba d -> (Word16, Word16, Word16, Word16)
+fromRgbaPremultipliedWord16 = toPremultipliedWord16 . fromRgbaWord16
+
+toPremultipliedWord16 ::
+	(Word16, Word16, Word16, Word16) -> (Word16, Word16, Word16, Word16)
+toPremultipliedWord16 (
+	fromIntegral -> r, fromIntegral -> g,
+	fromIntegral -> b, fromIntegral -> a ) = (r', g', b', a')
+	where
+	[r', g', b', a'] = fromIntegral <$> [
+		r * a `div` 0xffff, g * a `div` 0xffff, b * a `div` 0xffff,
+		a :: Word32 ]
+
+unPremultipliedWord16 :: (Word16, Word16, Word16, Word16) -> [Word16]
+unPremultipliedWord16 (
+	fromIntegral -> r, fromIntegral -> g,
+	fromIntegral -> b, fromIntegral -> a ) = fromIntegral <$> [
+		r * 0xffff `div'` a, g * 0xffff `div'` a, b * 0xff `div'` a,
+		a :: Word32 ]
+
+pattern RgbaPremultipliedDouble :: (Eq d, Fractional d) => d -> d -> d -> d -> Rgba d
+pattern RgbaPremultipliedDouble r g b a <-
+	(fromRgbaPremultipliedDouble -> (r, g, b, a))
+
+rgbaPremultipliedDouble :: (Ord d, Num d) => d -> d -> d -> d -> Maybe (Rgba d)
+rgbaPremultipliedDouble r g b a
+	| 0 <= r && r <= a, 0 <= g && g <= a, 0 <= b && b <= a,
+		0 <= a && a <= 1 = Just $ RgbaPremultipliedDouble_ r g b a
+	| otherwise = Nothing
+
+fromRgbaPremultipliedDouble :: (Eq d, Fractional d) => Rgba d -> (d, d, d, d)
+fromRgbaPremultipliedDouble = toPremultipliedDouble . fromRgbaDouble
+
+toPremultipliedDouble :: Fractional d => (d, d, d, d) -> (d, d, d, d)
+toPremultipliedDouble (r, g, b, a) = (r * a, g * a, b * a, a)
+
+unPremultipliedDouble :: (Eq d, Fractional d) => (d, d, d, d) -> [d]
+unPremultipliedDouble (r, g, b, a) = [r ./. a, g ./. a, b ./. a, a]
+
+div' :: Integral n => n -> n -> n
+0 `div'` 0 = 0
+a `div'` b = a `div` b
+
+(./.) :: (Eq a, Fractional a) => a -> a -> a
+0 ./. 0 = 0
+a ./. b = a / b
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
diff --git a/union-color.cabal b/union-color.cabal
new file mode 100644
--- /dev/null
+++ b/union-color.cabal
@@ -0,0 +1,49 @@
+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:           union-color
+version:        0.1.1.0
+description:    Please see the README on GitHub at <https://github.com/githubuser/union-color#readme>
+homepage:       https://github.com/githubuser/union-color#readme
+bug-reports:    https://github.com/githubuser/union-color/issues
+author:         Author name here
+maintainer:     example@example.com
+copyright:      2021 Author name here
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://github.com/githubuser/union-color
+
+library
+  exposed-modules:
+      Data.Color
+      Data.Color.Internal
+  other-modules:
+      Paths_union_color
+  hs-source-dirs:
+      src
+  build-depends:
+      base >=4.7 && <5
+  default-language: Haskell2010
+
+test-suite union-color-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_union_color
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , union-color
+  default-language: Haskell2010
