88-- We need this to have correct links inside haddocks
99{-# OPTIONS_GHC -Wno-unused-imports #-}
1010
11+ -- Required to use `showType` inside haddock coments
12+ {-# OPTIONS_GHC -Wno-unused-top-binds #-}
1113
1214{- |
1315= Introduction and intended usage
@@ -163,9 +165,37 @@ import Data.Kind (Constraint)
163165-- Imports for haddocks
164166import GHC.OverloadedLabels (IsLabel (.. ))
165167
168+ #if __GLASGOW_HASKELL__ >= 908
169+ import GHC.TypeError (Unsatisfiable )
170+
171+ showType :: forall a . (Unsatisfiable (ShowType a )) => ()
172+ showType = ()
173+ #endif
174+
175+ -- | Red, green, blue, and optional alpha color channels in range from 0 to 255
166176type WebColorParsed = (Nat , Nat , Nat , Maybe Nat )
167177
168- -- |
178+ -- | Parse a string containing a named color from a basic
179+ -- palette or hexadecimal representation with an optional
180+ -- alpha channel.
181+ --
182+ -- * Named colors are always considered RGB-only:
183+ --
184+ -- >>> showType @(`ParseWebColorMaybeAlpha` "red")
185+ -- '(255, 0, 0, 'Nothing)
186+ --
187+ -- >>> showType @(`ParseWebColorMaybeAlpha` "silver")
188+ -- '(192, 192, 192, 'Nothing)
189+ --
190+ -- `ParseWebColorMaybeAlpha` inherits many properties from `ParseHexadecimalColor`:
191+ --
192+ -- * The difference between a `Nothing` alpha channel and @`Just` 255@
193+ -- is purely syntactical, and you have to tackle the difference yourself
194+ -- * This family automatically handles shortened syntax
195+ -- * This family throws a compile-time error when the wrong number
196+ -- of hex characters is supplied
197+ --
198+ -- Please refer to `ParseHexadecimalColor` for the examples.
169199type ParseWebColorMaybeAlpha :: Symbol -> WebColorParsed
170200type family ParseWebColorMaybeAlpha s where
171201 ParseWebColorMaybeAlpha " white" = '(255 , 255 , 255 , Nothing )
@@ -186,6 +216,47 @@ type family ParseWebColorMaybeAlpha s where
186216 ParseWebColorMaybeAlpha " purple" = '(128 , 0 , 128 , Nothing )
187217 ParseWebColorMaybeAlpha s = ParseHexadecimalColor s
188218
219+ -- | Parse a string containing hexadecimal representation of a
220+ -- color with an optional alpha channel.
221+ --
222+ -- * This family doesn't handle named colors.
223+ -- * The difference between a `Nothing` alpha channel and @`Just` 255@
224+ -- is purely syntactical, and you have to tackle the difference yourself:
225+ --
226+ -- >>> showType @(`ParseHexadecimalColor` "fafefb")
227+ -- '(250, 254, 251, 'Nothing)
228+ --
229+ -- >>> showType @(`ParseHexadecimalColor` "fafefbff")
230+ -- '(250, 254, 251, 'Just 255)
231+ --
232+ -- * This family automatically handles shortened syntax:
233+ --
234+ -- E.g. #123 is the same as #112233:
235+ --
236+ -- >>> showType @(`ParseHexadecimalColor` "123")
237+ -- '(17, 34, 51, 'Nothing)
238+ --
239+ -- >>> showType @(`ParseHexadecimalColor` "112233")
240+ -- '(17, 34, 51, 'Nothing)
241+ --
242+ -- The same applies to #1234 and #11223344:
243+ --
244+ -- >>> showType @(`ParseHexadecimalColor` "1234")
245+ -- '(17, 34, 51, 'Just 68)
246+ --
247+ -- >>> showType @(`ParseHexadecimalColor` "11223344")
248+ -- '(17, 34, 51, 'Just 68)
249+ --
250+ -- * This family throws a compile-time error when the wrong number
251+ -- of hex characters is supplied:
252+ --
253+ -- >>> showType @(`ParseHexadecimalColor` "1")
254+ -- Unexpected number of hex codes
255+ -- expected 3, 4, 6 or 8
256+ --
257+ -- >>> showType @(`ParseHexadecimalColor` "1122334455")
258+ -- Unexpected number of hex codes
259+ -- expected 3, 4, 6 or 8
189260type ParseHexadecimalColor :: Symbol -> WebColorParsed
190261type family ParseHexadecimalColor s where
191262 ParseHexadecimalColor s = ParseColorRec '[] (UnconsSymbol s )
@@ -195,8 +266,36 @@ type family ParseColorRec color str where
195266 ParseColorRec colors Nothing = UpgradeColor colors
196267 ParseColorRec colors (Just '(ch , t )) = ParseColorRec (ParseHexadecimalChar ch : colors ) (UnconsSymbol t )
197268
269+ -- | Red, green, and blue color channels in range from 0 to 255
198270type WebColor = (Nat , Nat , Nat )
199271
272+ -- | Parse a string containing a named color from a basic
273+ -- palette or hexadecimal representation without an alpha channel.
274+ --
275+ -- * For convenience, a 255 alpha channel is interpreted
276+ -- as a solid color without an alpha channel:
277+ --
278+ -- >>> showType @(`ParseWebColor` "123")
279+ -- '(17, 34, 51)
280+ --
281+ -- >>> showType @(`ParseWebColor` "123f")
282+ -- '(17, 34, 51)
283+ --
284+ -- * Other alpha channel values result in a compile-time error:
285+ --
286+ -- >>> showType @(`ParseWebColor` "123d")
287+ -- Unexpected alpha channel! RGB color expected
288+ --
289+ -- This family inherits many properties from `ParseWebColorMaybeAlpha`:
290+ --
291+ -- * Named colors are always considered RGB-only:
292+ --
293+ -- >>> showType @(`ParseWebColor` "red")
294+ -- '(255, 0, 0)
295+ --
296+ -- * This family automatically handles shortened syntax.
297+ -- * This family throws a compile-time error when the wrong number
298+ -- of hex characters is supplied
200299type ParseWebColor :: Symbol -> WebColor
201300type family ParseWebColor s where
202301 ParseWebColor s = ParseRGBColorWorker (ParseWebColorMaybeAlpha s )
@@ -207,8 +306,29 @@ type family ParseRGBColorWorker color where
207306 ParseRGBColorWorker '(r , g , b , Just 255 ) = '(r , g , b )
208307 ParseRGBColorWorker '(_ , _ , _ , Just _ ) = TypeError (Text " Unexpected alpha channel! RGB color expected" )
209308
309+ -- | Red, green, blue, and alpha color channels in range from 0 to 255
210310type WebColorAlpha = (Nat , Nat , Nat , Nat )
211311
312+ -- | Parse a string containing a named color from a basic
313+ -- palette or a hexadecimal representation with an optional
314+ -- alpha channel.
315+ --
316+ -- * This family converts an absence of an alpha channel into
317+ -- the 255 value.
318+ --
319+ -- >>> showType @(`ParseWebColorAlpha` "123")
320+ -- '(17, 34, 51, 255)
321+ --
322+ -- This family inherits many properties from `ParseWebColorMaybeAlpha`:
323+ --
324+ -- * Named colors are always considered RGB-only and are handled the same way:
325+ --
326+ -- >>> showType @(`ParseWebColorAlpha` "red")
327+ -- '(255, 0, 0, 255)
328+ --
329+ -- * This family automatically handles shortened syntax.
330+ -- * This family throws a compile-time error when the wrong number
331+ -- of hex characters is supplied
212332type ParseWebColorAlpha :: Symbol -> WebColorAlpha
213333type family ParseWebColorAlpha s where
214334 ParseWebColorAlpha s = ParseRGBAColorWorker (ParseWebColorMaybeAlpha s )
@@ -220,8 +340,35 @@ type family ParseRGBAColorWorker color where
220340
221341type a & b = a
222342
343+ -- | Parse a type-level string containing a named color from a basic
344+ -- palette or a hexadecimal representation and convert it into three
345+ -- bytes representing red, green, and blue channels
346+ --
347+ --
348+ -- * For convenience, a 255 alpha channel is interpreted
349+ -- as a solid color without an alpha channel:
350+ --
351+ -- >>> webColor @"123" (,,)
352+ -- (17,34,51)
353+ --
354+ -- >>> webColor @"123f" (,,)
355+ -- (17,34,51)
356+ --
357+ -- * Other alpha channel values result in a compile-time error:
358+ --
359+ -- >>> webColor @"123d" (,,)
360+ -- Unexpected alpha channel! RGB color expected
361+ --
362+ -- * Named colors are always considered RGB-only:
363+ --
364+ -- >>> webColor @"red" (,,)
365+ -- (255,0,0)
223366type IsWebColor :: Symbol -> Constraint
224367class IsWebColor s where
368+ -- | Parse a type-level string and give you bytes representing
369+ -- red, green, and blue colors.
370+ --
371+ -- NB: @&@ is just a type alias that should help to keep with order.
225372 webColor ::
226373 (Word8 & " red" -> Word8 & " green" -> Word8 & " blue" -> r ) -> r
227374
@@ -237,8 +384,29 @@ instance {-# OVERLAPPABLE #-}
237384 webColor k =
238385 k `color` Proxy @ r `color` Proxy @ g `color` Proxy @ b
239386
387+ -- | Parse a type-level string containing a named color from a basic
388+ -- palette or a hexadecimal representation and convert it into four
389+ -- bytes representing red, green, blue, and alpha channels
390+ --
391+ --
392+ -- * An absent alpha channel get converted into the 255 value:
393+ --
394+ -- >>> webColorAlpha @"123" (,,,)
395+ -- (17,34,51,255)
396+ --
397+ -- >>> webColorAlpha @"123f" (,,,)
398+ -- (17,34,51,255)
399+ --
400+ -- * Named colors are always considered RGB-only:
401+ --
402+ -- >>> webColorAlpha @"red" (,,,)
403+ -- (255,0,0,255)
240404type IsWebColorAlpha :: Symbol -> Constraint
241405class IsWebColorAlpha s where
406+ -- | Parse a type-level string and give you bytes representing
407+ -- red, green, blue, and alpha colors.
408+ --
409+ -- NB: @&@ is just a type alias that should help to keep with order.
242410 webColorAlpha ::
243411 (Word8 & " red" -> Word8 & " green" -> Word8 & " blue" -> Word8 & " alpha" -> r ) -> r
244412
0 commit comments