relude-0.7.0.0: Safe, performant, user-friendly and lightweight Haskell Standard Library

Copyright(c) 2018-2020 Kowainik
LicenseMIT
MaintainerKowainik <xrom.xkov@gmail.com>
StabilityExperimental
PortabilityPortable
Safe HaskellSafe
LanguageHaskell2010

Relude.Extra.Enum

Description

Mini bounded-enum framework inside relude.

Since: 0.1.0

Synopsis

Documentation

universe :: (Bounded a, Enum a) => [a] Source #

Returns all values of some Bounded Enum in ascending order.

>>> universe :: [Bool]
[False,True]
>>> universe @Ordering
[LT,EQ,GT]
>>> data TrafficLight = Red | Blue | Green deriving (Show, Enum, Bounded)
>>> universe :: [TrafficLight]
[Red,Blue,Green]
>>> data Singleton = Singleton deriving (Show, Enum, Bounded)
>>> universe @Singleton
[Singleton]

Since: 0.1.0

universeNonEmpty :: forall a. (Bounded a, Enum a, Eq a) => NonEmpty a Source #

Like universe, but returns NonEmpty list of some enumeration

>>> universeNonEmpty :: NonEmpty Bool
False :| [True]
>>> universeNonEmpty @Ordering
LT :| [EQ,GT]
>>> data TrafficLight = Red | Blue | Green deriving (Show, Eq, Enum, Bounded)
>>> universeNonEmpty :: NonEmpty TrafficLight
Red :| [Blue,Green]
>>> data Singleton = Singleton deriving (Show, Eq, Enum, Bounded)
>>> universeNonEmpty @Singleton
Singleton :| []

Since: 0.7.0.0

inverseMap :: forall a k. (Bounded a, Enum a, Ord k) => (a -> k) -> k -> Maybe a Source #

inverseMap f creates a function that is the inverse of a given function f. It does so by constructing Map internally for each value f a. The implementation makes sure that the Map is constructed only once and then shared for every call.

Memory usage note: don't inverse functions that have types like Int as their result. In this case the created Map will have huge size.

The complexity of reversed mapping is \(\mathcal{O}(\log n)\).

Performance note: make sure to specialize monomorphic type of your functions that use inverseMap to avoid Map reconstruction.

One of the common inverseMap use-case is inverting the show or a show-like function.

>>> data Color = Red | Green | Blue deriving (Show, Enum, Bounded)
>>> parse = inverseMap show :: String -> Maybe Color
>>> parse "Red"
Just Red
>>> parse "Black"
Nothing

Correctness note: inverseMap expects injective function as its argument, i.e. the function must map distinct arguments to distinct values.

Typical usage of this function looks like this:

data GhcVer
    = Ghc802
    | Ghc822
    | Ghc844
    | Ghc865
    | Ghc881
    deriving (Eq, Ord, Show, Enum, Bounded)

showGhcVer :: GhcVer -> Text
showGhcVer = \case
    Ghc802 -> "8.0.2"
    Ghc822 -> "8.2.2"
    Ghc844 -> "8.4.4"
    Ghc865 -> "8.6.5"
    Ghc881 -> "8.8.1"

parseGhcVer :: Text -> Maybe GhcVer
parseGhcVer = inverseMap showGhcVer

Since: 0.1.1

next :: (Eq a, Bounded a, Enum a) => a -> a Source #

Like succ, but doesn't fail on maxBound. Instead it returns minBound.

>>> next False
True
>>> next True
False
>>> succ True
*** Exception: Prelude.Enum.Bool.succ: bad argument

Since: 0.1.0

prev :: (Eq a, Bounded a, Enum a) => a -> a Source #

Like pred, but doesn't fail on minBound. Instead it returns maxBound.

>>> prev False
True
>>> prev True
False
>>> pred False
*** Exception: Prelude.Enum.Bool.pred: bad argument

Since: 0.6.0.0

safeToEnum :: forall a. (Bounded a, Enum a) => Int -> Maybe a Source #

Returns Nothing if given Int outside range.

>>> safeToEnum @Bool 0
Just False
>>> safeToEnum @Bool 1
Just True
>>> safeToEnum @Bool 2
Nothing
>>> safeToEnum @Bool (-1)
Nothing

Since: 0.1.0