packages feed

antelude (empty) → 0.1.0

raw patch · 23 files changed

+2601/−0 lines, 23 filesdep +HUnitdep +anteludedep +array

Dependencies added: HUnit, antelude, array, base, bytestring, containers, text

Files

+ CHANGELOG.md view
@@ -0,0 +1,29 @@+###### 0.1.0:++Lots of stuff. Like, all of them. The init. Not sure how to _really_ document this but here we go:++- Antelude main module, exposing a lot of symbol-functions, a few named-functions, and a lot of types and typeclasses.+- Antelude.Array for Array stuff+- Antelude.Bool for Bool stuff+- Antelude.Either for Either stuff+- Antelude.File for File stuff+- Antelude.Function for functional stuff+- Antelude.IO for IO stuff+- Antelude.List for List stuff+- Antelude.List.NonEmpty for NonEmpty stuff+- Antelude.Maybe for Maybe stuff+- Antelude.Monad for Monad stuff+- Antelude.Numeric for numeric stuff+- Antelude.Result for Result stuff+- Antelude.Sequence for Sequence stuff+- Antelude.String for String stuff+- Antelude.String.Case for Case stuff+- Antelude.Tuple.Pair for Pair stuff+- Antelude.Tuple.Trio for Trio stuff+- Test for all of the new stuff from above+- Documentation+- This very changelog you are reading right now+- Licensing (MIT)+- Justfile so I remember commands+- Readme+- Format all the things
+ LICENSE view
@@ -0,0 +1,9 @@+MIT License++Copyright (c) 2024 dneaves++Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ antelude.cabal view
@@ -0,0 +1,79 @@+cabal-version: 3.4+name:          antelude+version:       0.1.0+synopsis:      Yet another alternative Prelude for Haskell.+description:+  A Prelude with an intention to simplify the global scope, fix up a few things, add a few things, and be as dev-friendly for everyone as possible.++author:        dneaves+maintainer:    dneavesdev@pm.me+homepage:      https://codeberg.org/dneaves/antelude+bug-reports:   https://codeberg.org/dneaves/antelude/issues+license:       MIT+license-file:  LICENSE+copyright: © 2024 dneaves+category:      Prelude+build-type:    Simple+tested-with: GHC == 9.6.4+             GHC == 9.8.2+             GHC == 9.10.1+extra-doc-files:     CHANGELOG.md++source-repository head+  type:     git+  location: git@codeberg.org:dneaves/antelude.git++common warnings+  ghc-options: -Wall++common extensions+  default-extensions:+    NoGeneralizedNewtypeDeriving+    NoImplicitPrelude+    InstanceSigs+    LambdaCase+    MultiWayIf+    Safe+    ScopedTypeVariables++library+  import:           warnings, extensions+  default-language: GHC2021+  hs-source-dirs:   src+  exposed-modules:+    Antelude+    Antelude.Array+    Antelude.Bool+    Antelude.Either+    Antelude.File+    Antelude.Function+    Antelude.IO+    Antelude.List+    Antelude.List.NonEmpty+    Antelude.Maybe+    Antelude.Monad+    Antelude.Numeric+    Antelude.Result+    Antelude.Sequence+    Antelude.String+    Antelude.String.Case+    Antelude.Tuple.Pair+    Antelude.Tuple.Trio+  other-modules:    Antelude.Internal.TypesClasses+  build-depends:+    , array >= 0.5.6 && < 0.6+    , base >= 4.18.2 && < 4.21+    , bytestring >= 0.11.5 && < 0.13+    , containers >= 0.6.7 && < 0.8+    , text >= 2.0.2 && < 2.2++test-suite antelude-test+  import:           warnings, extensions+  default-language: GHC2021+  hs-source-dirs:   test+  type:             exitcode-stdio-1.0+  main-is:          Main.hs+  build-depends:+    , antelude >= 0.1.0 && < 0.1.1+    , base >= 4.18.2 && < 4.21+    , HUnit >= 1.6.2 && < 1.7
+ src/Antelude.hs view
@@ -0,0 +1,258 @@+{- |+Module      : Antelude+Description : Yet another alternative Prelude for Haskell+Copyright   : (c) David Neave, 2024+License     : MIT+Maintainer  : dneavesdev@pm.me+This is just what's available in the global scope. It is intended this way to encourage qualified or named-exposure imports, to give clarity to everyone reading your code where something came from.++For everything else you require, you are encouraged to:++* See if there's an Antelude module containing what you're looking for (ex.: Antelude.List: 'Antelude.List')++* See if there's a base package containing what you're looking for (ex.: Data.Char: 'Data.Char', Control.Applicative: 'Control.Applicative')++* See if there's an external package containing what you're looking for (ex.: Data.Text.Lazy.IO: 'Data.Text.Lazy.IO' from the "text" package)+-}+module Antelude+    ( -- * Symbols and Functions+      -- ** Symbols+      -- *** Function Piping and Composition+      (.>)+    , (<.)+    , (<|)+    , (|>)+      -- *** Monadic Stuff+      -- | Reexport from 'Control.Monad'+    , (=<<)+      -- | Reexport from 'Control.Monad'+    , (<<)+    , (>=>)+      -- | Reexport from 'Control.Monad'+    , (<=<)+      -- *** Boolean+      -- | Reexport from 'Data.Bool'+    , (&&)+      -- | Reexport from 'Data.Bool'+    , (||)+      -- *** Functors+      -- | Reexport from 'Data.Functor'+    , ($>)+      -- | Reexport from 'Data.Functor'+    , (<$>)+      -- | Reexport from 'Data.Functor'+    , (<&>)+      -- *** Numeric Non-Class+      -- | Reexport from 'Prelude'+    , (^)+      -- | Reexport from 'Prelude'+    , (^^)+      -- *** Strictly Apply+      -- | Reexport from 'Prelude'+    , ($!)+      -- ** Functions+      -- | Often used as a catch-all case for multi-way-ifs and guards. Is always 'True'.+    , ABool.otherwise+      -- | 'Show'/'print' something to stdout.+    , Pre.print+      -- * Types and Classes+      -- ** Types+      -- *** Basics+      -- | Reexport from 'Data.Bool'+    , Bool (..)+      -- | Reexport from 'Data.Char'+    , Char+      -- | Reexport from 'Data.String'+    , String+      -- | Reexport from 'Data.Int'+    , Int+      -- | Reexport from 'Prelude'+    , Integer+      -- | Reexport from 'Prelude'+    , Float+      -- | Reexport from 'Prelude'+    , Double+      -- | Reexport from 'Data.Ratio'+    , Rational+      -- | Reexport from 'Data.Word'+    , Word+      -- *** Container-Types+      -- **** List and List-ish+      -- | Reexport from 'Data.List'+    , List+      -- | Reexport from 'Data.List.NonEmpty'+    , NonEmpty (..)+      -- | Reexport from 'Data.Array' of the "array" package+    , Array+      -- **** Formally-Named Tuples+    , Pair+    , Trio+      -- *** External-Package-Types+    , ByteString+    , ByteStringLazy+    , Map+    , MapLazy+    , Text+    , TextLazy+      -- | Reexport from 'Data.Set' of the "containers" package+    , Set+      -- | Reexport from 'Data.Sequence' of the "containers" package+    , Seq+      -- *** Other Important Things+      -- | Reexport from 'Data.Maybe'+    , Maybe (..)+      -- | Reexport from 'Data.Either'+    , Either (..)+    , Result (..)+      -- | Reexport from 'Data.Ord'+    , Ordering (..)+      -- | Reexport from 'Text.Show'+    , ShowS+      -- | Reexport from 'Text.Read'+    , ReadS+      -- | Reexport from 'System.IO'+    , IO+      -- | Reexport from 'System.IO'+    , FilePath+      -- | Reexport from 'System.IO.Error'+    , IOError+      -- | Reexport from 'Data.Void'+    , Void+      -- ** Classes+      -- *** Numeric Classes+      -- | Reexport from 'Prelude'+    , Num ((+), (-), (*))+      -- | Reexport from 'Prelude'+    , Real+      -- | Reexport from 'Prelude'+    , Integral+      -- | Reexport from 'Prelude'+    , Fractional ((/))+      -- | Reexport from 'Prelude'+    , Floating ((**))+      -- | Reexport from 'Prelude'+    , RealFrac+      -- | Reexport from 'Prelude'+    , RealFloat+      -- *** The "Theorum-Based" Classes+      -- | Reexport from 'Data.Semigroup'+    , Semigroup ((<>))+      -- | Reexport from 'Data.Monoid'+    , Monoid+      -- | Reexport from 'Control.Monad'+    , Functor (..)+      -- | Reexport from 'Control.Applicative'+    , Alternative (empty, (<|>))+    , Applicative (..)+      -- | Reexport from 'Control.Monad'+    , Monad (..)+      -- | Reexport from 'Control.Monad.IO.Class'+    , MonadIO (..)+      -- | Reexport from 'Control.Monad'+    , MonadPlus+      -- | Reexport from 'Control.Monad.Fail'+    , MonadFail+      -- *** The Rest of the Classes+      -- | Reexport from 'Data.Eq'+    , Eq (..)+      -- | Reexport from 'Data.Ord'+    , Ord ((<), (>), (<=), (>=))+      -- | Reexport from 'Prelude'+    , Enum+      -- | Reexport from 'Prelude'+    , Bounded+      -- | Reexport from 'Data.Foldable'+    , Foldable+      -- | Reexport from 'Data.Traversable'+    , Traversable+      -- | Reexport from 'Text.Show'+    , Show (show, showList)+      -- | Reexport from 'Text.Read'+    , Read+    ) where++import safe           Antelude.Bool                  as ABool+    ( otherwise+    , (&&)+    , (||)+    )+import safe           Antelude.Function              as AFunc+    ( (.>)+    , (<.)+    , (<|)+    , (|>)+    )+import safe           Antelude.Internal.TypesClasses as AITC+    ( Alternative (empty, (<|>))+    , Applicative (..)+    , Array+    , Bool (..)+    , Bounded+    , ByteString+    , ByteStringLazy+    , Char+    , Double+    , Either (..)+    , Enum+    , Eq (..)+    , FilePath+    , Float+    , Floating ((**))+    , Foldable+    , Fractional ((/))+    , Functor (..)+    , IO+    , IOError+    , Int+    , Integer+    , Integral+    , List+    , Map+    , MapLazy+    , Maybe (..)+    , Monad (..)+    , MonadFail+    , MonadIO (..)+    , MonadPlus+    , Monoid+    , NonEmpty (..)+    , Num ((*), (+), (-))+    , Ord ((<), (<=), (>), (>=))+    , Ordering (..)+    , Pair+    , Rational+    , Read+    , ReadS+    , Real+    , RealFloat+    , RealFrac+    , Result (..)+    , Semigroup ((<>))+    , Seq+    , Set+    , Show (show, showList)+    , ShowS+    , String+    , Text+    , TextLazy+    , Traversable+    , Trio+    , Void+    , Word+    )+import safe           Antelude.Monad                 as AMonad+    ( ($>)+    , (<<)+    , (<=<)+    , (=<<)+    , (>=>)+    )++import safe           Data.Functor                   ( (<$>), (<&>) )++import safe           Prelude                        as Pre+    ( print+    , ($!)+    , (^)+    , (^^)+    )
+ src/Antelude/Array.hs view
@@ -0,0 +1,84 @@+{- |+Module      : Antelude.Array+Description : Contains some functions for Arrays, and reexports the Data.Array module.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Array+    ( -- * Rexports+    module ArrayExport+    -- * New and Reconstructed for safety+    , atIndex+    , enumerate+    , fromList+    , fromNonEmpty+    , map+    , toList+    , toNonEmpty+    , update+    ) where++import safe           Antelude.Bool                  ( and )+import safe           Antelude.Function              ( flip, (|>) )+import safe           Antelude.Internal.TypesClasses+    ( Functor (fmap)+    , List+    , Maybe (..)+    , NonEmpty+    )+import safe qualified Antelude.List.NonEmpty         as NE ( fromList, toList )+import safe           Antelude.Tuple.Pair            ( first, second )++import safe           Data.Array                     as ArrayExport hiding+    ( assocs+    , elems+    , listArray+    , (//)+    , (!)+    )+import safe qualified Data.Array                     as Array++import safe           Prelude                        ( (<=), (>=) )+++-- | This is here for parity with Data.List. The definition is just 'fmap' from 'Functor'.+map :: (e -> f) -> Array i e -> Array i f+map = fmap+++-- | Convert a 'List' to an 'Array' along with a pair of bounds.+fromList :: (Array.Ix i) => (i, i) -> List a -> Array i a+fromList = Array.listArray+++-- | Convert an 'Array' to a 'List'.+toList :: Array i e -> List e+toList = Array.elems+++-- | Enumerate an 'Array' into a 'List' of indices i and elements e.+enumerate :: (Array.Ix i) => Array i e -> List (i, e)+enumerate = Array.assocs+++-- | Convert a 'NonEmpty' to an 'Array' along with a pair of bounds.+fromNonEmpty :: (Array.Ix i) => (i, i) -> NonEmpty a -> Array i a+fromNonEmpty bound ne = NE.toList ne |> fromList bound++-- | Convert an 'Array' to a 'NonEmpty'.+toNonEmpty :: (Array.Ix i) => Array i a -> Maybe (NonEmpty a)+toNonEmpty arr = toList arr |> NE.fromList+++-- | Reconstruct an 'Array' with the given 'List' of indices i and elements e in their designated positions.+update :: (Array.Ix i) => List (i, e) -> Array i e -> Array i e+update = flip (Array.//)+++-- | Obtain the element at the given index. 'Nothing' if the index is not valid.+atIndex :: (Array.Ix i) => i -> Array i e -> Maybe e+atIndex idx arr =+  if (idx >= first (Array.bounds arr)) `and` (idx <= second (Array.bounds arr))+    then+      (Array.!) arr idx |> Just+    else+      Nothing
+ src/Antelude/Bool.hs view
@@ -0,0 +1,55 @@+{- |+Module      : Antelude.Bool+Description : Contains some functions for Bools.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Bool+    ( Bool (..)+    , all+    , and+    , any+    , not+    , or+    , otherwise+    , xor+    , (&&)+    , (||)+    ) where++import safe           Antelude.Internal.TypesClasses ( Bool (..), List )++import safe           Prelude+    ( not+    , otherwise+    , (&&)+    , (||)+    )+import safe qualified Prelude                        ( and, or )++infixr 3 `and`++-- | Logical `and`, but in word form. Can be used normally or infixed.+and :: Bool -> Bool -> Bool+and a b = a && b++infixr 2 `or`++-- | Logical `or`, but in word form. Can be used normally or infixed.+or :: Bool -> Bool -> Bool+or a b = a || b++infixr 1 `xor`++-- | Logical `xor`, but in word form. Can be used normally or infixed.+xor :: Bool -> Bool -> Bool+xor a b = (a `and` Prelude.not b) `or` (Prelude.not a `and` b)+++-- | Return 'True' if 'all' of the contents of the list evaluate to 'True'.+all :: List Bool -> Bool+all = Prelude.and+++-- | Return 'True' if 'any' of the contents of the list evaluate to 'True'.+any :: List Bool -> Bool+any = Prelude.or
+ src/Antelude/Either.hs view
@@ -0,0 +1,93 @@+{- |+Module      : Antelude.Either+Description : Contains some functions for Eithers.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Either+    ( Either (..)+      -- * Rexports+    , Either.either+    , Either.isLeft+    , Either.isRight+      -- * New and Reconstructed for safety+    , filterLefts+    , filterRights+    , fromMaybe+    , fromResult+    , leftWithDefault+    , mapLeft+    , mapRight+    , partition+    , rightWithDefault+    , swap+    ) where++import safe           Antelude.Internal.TypesClasses+    ( Either (..)+    , List+    , Maybe (..)+    , Result (..)+    )++import safe qualified Data.Either                    as Either+++-- | Convert a 'Result a b' to an 'Either a b'.+fromResult :: Result err ok -> Either err ok+fromResult = \case+  Err err -> Left err+  Ok ok -> Right ok+++-- | Convert a 'Maybe a' to an 'Either () a'.+fromMaybe :: Maybe a -> Either () a+fromMaybe = \case+  Just a -> Right a+  Nothing -> Left ()+++-- | Apply a function to the 'Left' case of an 'Either'.+mapLeft :: (left -> newLeft) -> Either left right -> Either newLeft right+mapLeft leftFn (Left left) = Left (leftFn left)+mapLeft _ (Right right)    = Right right+++-- | Apply a function to the 'Right' case of an 'Either'.+mapRight :: (right -> newRight) -> Either left right -> Either left newRight+mapRight rightFn (Right right) = Right (rightFn right)+mapRight _ (Left left)         = Left left+++-- | Swap the 'Left'/'Right' in an 'Either'+swap :: Either left right -> Either right left+swap (Left a)  = Right a+swap (Right a) = Left a+++-- | Get the 'Left' case of an 'Either', or a default if the 'Either' is 'Right'.+leftWithDefault :: a -> Either a b -> a+leftWithDefault dflt = \case+  Left a -> a+  Right _ -> dflt+++-- | Get the 'Right' case of an 'Either', or a default if the 'Either' is 'Left'.+rightWithDefault :: b -> Either a b -> b+rightWithDefault dflt = \case+  Left _ -> dflt+  Right b -> b+++-- | Take a 'List' of 'Either left right' and create a Tuple with 'List left' and 'List right'.+partition :: List (Either left right) -> (List left, List right)+partition = Either.partitionEithers+++-- | Take a 'List' of 'Either a b' and return a 'List' containing all of the values from the 'Left' cases.+filterLefts :: List (Either left right) -> List left+filterLefts = Either.lefts+++-- | Take a 'List' of 'Either a b' and return a 'List' containing all of the values from the 'Right' cases.+filterRights :: List (Either left right) -> List right+filterRights = Either.rights
+ src/Antelude/File.hs view
@@ -0,0 +1,22 @@+{- |+Module      : Antelude.File+Description : Contains some basic functions for dealing with files.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.File+    ( FilePath+      -- | Reexport from 'Prelude'+    , P.appendFile+      -- | Reexport from 'Prelude'+    , P.readFile+      -- | Reexport from 'Prelude'+    , P.writeFile+    ) where++import safe           Antelude.Internal.TypesClasses ( FilePath )++import safe qualified Prelude                        as P+    ( appendFile+    , readFile+    , writeFile+    )
+ src/Antelude/Function.hs view
@@ -0,0 +1,73 @@+{- |+Module      : Antelude.Function+Description : Contains some functional functions and symbols.+Maintainer  : dneavesdev@pm.me++I realized after-the-fact that the arrows (which I was taking inspiration from Elm) is essentially part of what the 'flow' package does.+-}+module Antelude.Function+    ( constant+    , identity+      -- | Reexport from 'Data.Function'+    , Prelude.flip+      -- | Reexport from 'Prelude'+    , Prelude.asTypeOf+      -- | Reexport from 'Prelude'+    , Prelude.seq+      -- operators+    , (.>)+    , (<.)+    , (<|)+    , (|>)+    ) where++import safe qualified Prelude+++-- | Re-return the first argument. Can be surprisingly useful.+identity :: a -> a+identity = Prelude.id+++-- | Always return the first argument.+constant :: a -> b -> a+constant = Prelude.const+++infixr 0 <|+++-- | Equivalent to '($)' from 'Data.Function', but like Elm. Can be slightly clearer for unfamiliar developers.+(<|) :: (a -> b) -> a -> b+a <| b = a b++infixl 0 |>+++-- | Equivalent to '(&)' from 'Data.Function', but like Elm. Can be slightly clearer for unfamiliar developers.+(|>) :: a -> (a -> b) -> b+a |> b = b a+++infixl 9 <.+++{- |+   Equivalent to '(.)' from 'Data.Function', but in an arrowhead format.++   Since '(<<)' would be confused with 'flip (>>)', '(<.)' was decided as it's `(.)` but with a direction.+-}+(<.) :: (b -> c) -> (a -> b) -> a -> c+a <. b = \x -> a <| b x+++infixr 9 .>+++{- |+   Equivalent to 'flip (.)', but in an arrowhead format.++   Since '(>>)' is already a typeclass-locked Haskell symbol for `Monad`, '(.>)' was decided as was decided as it's `(.)` but with a direction.+-}+(.>) :: (a -> b) -> (b -> c) -> a -> c+a .> b = \x -> b <| a x
+ src/Antelude/IO.hs view
@@ -0,0 +1,72 @@+{- |+Module      : Antelude.IO+Description : Contains some functions for basic IO stuff.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.IO+    ( IO+    , IOError+    , MonadIO (..)+    -- | Reexport from 'Control.Exception'+    , Exception+    -- | Reexport from 'Prelude'+    , P.error+    -- | Reexport from 'Prelude'+    , P.errorWithoutStackTrace+    -- | Reexport from 'Prelude'+    , P.getChar+    -- | Reexport from 'Prelude'+    , P.getContents+    -- | Reexport from 'Prelude'+    , P.getLine+    -- | Reexport from 'Prelude'+    , P.interact+    -- | Reexport from 'Prelude'+    , P.ioError+    -- | Reexport from 'Prelude'+    , P.putChar+    -- | Reexport from 'Preluded'+    , P.putStr+    -- | Reexport from 'Preluded'+    , P.putStrLn+    -- | Reexport from 'Preluded'+    , P.readIO+    -- | Reexport from 'Preluded'+    , P.readLn+    -- | Reexport from 'Preluded'+    , P.undefined+    -- | Reexport from 'Preluded'+    , P.userError+    -- | Reexport from 'Control.Exception'+    , Ex.try+    -- | Reexport from 'Control.Exception'+    , Ex.handle+    -- | Reexport from 'Control.Exception'+    , Ex.catch+    ) where++import safe           Antelude.Internal.TypesClasses+    ( IO+    , IOError+    , MonadIO (..)+    )++import safe           Control.Exception              ( Exception )+import safe qualified Control.Exception              as Ex++import safe qualified Prelude                        as P+    ( error+    , errorWithoutStackTrace+    , getChar+    , getContents+    , getLine+    , interact+    , ioError+    , putChar+    , putStr+    , putStrLn+    , readIO+    , readLn+    , undefined+    , userError+    )
+ src/Antelude/Internal/TypesClasses.hs view
@@ -0,0 +1,245 @@+{- |+Module      : Antelude.Internal.TypesClasses+Description : Just contains Antelude's internal base of types and typeclasses.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Internal.TypesClasses+  ( -- * Types+    -- ** Basics+    -- | Reexport from 'Data.Bool'+    Bool (..)+    -- | Reexport from 'Data.Char'+  , Char+    -- | Reexport from 'Data.String'+  , String+    -- | Reexport from 'Data.Int'+  , Int+    -- | Reexport from 'Prelude'+  , Integer+    -- | Reexport from 'Prelude'+  , Float+    -- | Reexport from 'Prelude'+  , Double+    -- | Reexport from 'Data.Ratio'+  , Rational+    -- | Reexport from 'Data.Word'+  , Word+    -- ** Container-Types+    -- *** List and List-ish+    -- | Reexport from 'Data.List'+  , List+    -- | Reexport from 'Data.List.NonEmpty'+  , NonEmpty (..)+    -- | Reexport from 'Data.Array' of the "array" package+  , Array+    -- *** Formally-Named Tuples+  , Pair+  , Trio+    -- ** External-Package-Types+  , ByteString+  , ByteStringLazy+  , Map+  , MapLazy+  , Text+  , TextLazy+    -- | Reexport from 'Data.Set' of the "containers" package+  , Set+    -- | Reexport from 'Data.Sequence' of the "containers" package+  , Seq+    -- ** Other Important Things+    -- | Reexport from 'Data.Maybe'+  , Maybe (..)+    -- | Reexport from 'Data.Either'+  , Either (..)+  , Result (..)+    -- | Reexport from 'Data.Ord'+  , Ordering (..)+    -- | Reexport from 'Text.Show'+  , ShowS+    -- | Reexport from 'Text.Read'+  , ReadS+    -- | Reexport from 'System.IO'+  , IO+    -- | Reexport from 'System.IO'+  , FilePath+    -- | Reexport from 'System.IO.Error'+  , IOError+    -- | Reexport from 'Data.Void'+  , Void+    -- * Classes+    -- ** Numeric Classes+    -- | Reexport from 'Prelude'+  , Num ((+), (-), (*))+    -- | Reexport from 'Prelude'+  , Real+    -- | Reexport from 'Prelude'+  , Integral+    -- | Reexport from 'Prelude'+  , Fractional ((/))+    -- | Reexport from 'Prelude'+  , Floating ((**))+    -- | Reexport from 'Prelude'+  , RealFrac+    -- | Reexport from 'Prelude'+  , RealFloat+    -- ** The "Theorum-Based" Classes+    -- | Reexport from 'Data.Semigroup'+  , Semigroup ((<>))+    -- | Reexport from 'Data.Monoid'+  , Monoid+    -- | Reexport from 'Control.Monad'+  , Functor (..)+    -- | Reexport from 'Control.Applicative'+  , Alternative (empty, (<|>))+  , Applicative (..)+    -- | Reexport from 'Control.Monad'+  , Monad (..)+    -- | Reexport from 'Control.Monad.IO.Class'+  , MonadIO (..)+    -- | Reexport from 'Control.Monad'+  , MonadPlus+    -- | Reexport from 'Control.Monad.Fail'+  , MonadFail+    -- ** The Rest of the Classes+    -- | Reexport from 'Data.Eq'+  , Eq (..)+    -- | Reexport from 'Data.Ord'+  , Ord ((<), (>), (<=), (>=))+    -- | Reexport from 'Prelude'+  , Enum+    -- | Reexport from 'Prelude'+  , Bounded+    -- | Reexport from 'Data.Foldable'+  , Foldable+    -- | Reexport from 'Data.Traversable'+  , Traversable+    -- | Reexport from 'Text.Show'+  , Show (show, showList)+    -- | Reexport from 'Text.Read'+  , Read+  ) where++import safe           Control.Applicative    ( Alternative (..) )+import safe           Control.Monad          ( MonadPlus (..) )+import safe           Control.Monad.IO.Class ( MonadIO (..) )++import safe           Data.Array             ( Array )+import safe qualified Data.ByteString        as BS ( ByteString )+import safe qualified Data.ByteString.Lazy   as BL ( ByteString )+import safe           Data.List.NonEmpty     ( NonEmpty (..) )+import safe qualified Data.Map               as MapL ( Map )+import safe qualified Data.Map.Strict        as MapS ( Map )+import safe           Data.Sequence          ( Seq (..) )+import safe           Data.Set               ( Set )+import safe qualified Data.Text              as TS ( Text )+import safe qualified Data.Text.Lazy         as TL ( Text )+import safe           Data.Void              ( Void )++import safe           Prelude+  ( Applicative (..)+  , Bool (..)+  , Bounded (..)+  , Char+  , Double+  , Either (..)+  , Enum (..)+  , Eq (..)+  , FilePath+  , Float+  , Floating (..)+  , Foldable (..)+  , Fractional (..)+  , Functor (..)+  , IO+  , IOError+  , Int+  , Integer+  , Integral (..)+  , Maybe (..)+  , Monad (..)+  , MonadFail (..)+  , Monoid (..)+  , Num (..)+  , Ord (..)+  , Ordering (..)+  , Rational+  , Read (..)+  , ReadS+  , Real (..)+  , RealFloat (..)+  , RealFrac (..)+  , Semigroup (..)+  , Show (..)+  , ShowS+  , String+  , Traversable (..)+  , Word+  )+++-- | Explicit naming of the 'List' brackets.+type List a = [a]+++-- | A two-element Tuple+type Pair a b = (a, b)+++-- | A three-element Tuple+type Trio a b c = (a, b, c)+++-- | Aliased reexport from 'Data.Text' of the "text" package+type Text = TS.Text+++-- | Aliased reexport from 'Data.ByteString' of the "bytestring" package+type ByteString = BS.ByteString+++-- | Aliased reexport from 'Data.Text.Lazy' of the "text" package+type TextLazy = TL.Text+++-- | Aliased reexport from 'Data.ByteString.Lazy' of the "bytestring" package+type ByteStringLazy = BL.ByteString+++-- | Aliased reexport from 'Data.Map.Strict' of the "containers" package+type Map key val = MapS.Map key val+++-- | Aliased reexport from 'Data.Map.Lazy' of the "containers" package+type MapLazy key val = MapL.Map key val+++{- |+   The 'Result err ok' type, with variants `Err err` and 'Ok ok'.+   Similar to the 'Either' type, but with better naming, and disambiguates the purposes.+-}+data Result err ok+  = Err err+  | Ok ok+  deriving (Eq, Ord, Read, Show)+++instance Functor (Result err) where+  fmap :: (okA -> okB) -> Result err okA -> Result err okB+  fmap _ (Err err) = Err err+  fmap fn (Ok ok)  = Ok (fn ok)+++instance Applicative (Result err) where+  pure :: ok -> Result err ok+  pure = Ok+++  (<*>) :: Result err (okA -> okB) -> Result err okA -> Result err okB+  Err err <*> _  = Err err+  Ok okFn <*> ok = fmap okFn ok+++instance Monad (Result err) where+  (>>=) :: Result err okA -> (okA -> Result err okB) -> Result err okB+  Err err >>= _ = Err err+  Ok ok >>= fn  = fn ok
+ src/Antelude/List.hs view
@@ -0,0 +1,120 @@+{- |+Module      : Antelude.List+Description : Contains some functions for Lists, and reexports the Data.List module.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.List+    ( -- * Rexports+      module ListExp+      -- * New and Reconstructed for safety+    , append+    , atIndex+    , combine+    , cons+    , contains+    , difference+    , head+    , init+    , last+    , prepend+    , tail+    ) where++import safe           Antelude.Function              ( (<|), (|>) )+import safe           Antelude.Internal.TypesClasses+    ( Bool+    , Eq+    , Int+    , Maybe (..)+    , Ordering (..)+    )+import safe qualified Antelude.Internal.TypesClasses as ATC ( List )++import safe           Data.List                      as ListExp hiding+    ( head+    , init+    , last+    , tail+    , (++)+    , (\\)+    )+import safe qualified Data.List                      as List++import safe           Prelude                        ( Ord (compare) )+++-- | A safe implementation of 'head'. Returns 'Nothing' if if the 'List' is empty.+head :: ATC.List a -> Maybe a+head lst = case lst of+  []    -> Nothing+  [x]   -> Just x+  x : _ -> Just x+++-- | A safe implementation of 'last'. Returns 'Nothing' if if the 'List' is empty.+last :: ATC.List a -> Maybe a+last lst = case List.reverse lst of+  []    -> Nothing+  [x]   -> Just x+  x : _ -> Just x+++-- | A safe implementation of 'tail'. Returns 'Nothing' if if the 'List' is empty.+tail :: ATC.List a -> Maybe (ATC.List a)+tail lst = case lst of+  _ : xs -> Just xs+  _      -> Nothing+++-- | A safe implementation of 'init'. Returns 'Nothing' if if the 'List' is empty.+init :: ATC.List a -> Maybe (ATC.List a)+init lst = case List.reverse lst of+  _ : xs -> Just <| List.reverse xs+  _      -> Nothing+++{- |+   Obtain the element at the given index, starting at 0. 'Nothing' if the index is not valid.+-}+atIndex :: Int -> ATC.List a -> Maybe a+atIndex index lst = case compare index 0 of+  LT ->+    Nothing+  _ ->+    lst+      |> List.drop+        index+      |> head++-- | Defined as 'Data.List.elem'. See if something is a member of a list+contains :: Eq a => a -> ATC.List a -> Bool+contains = List.elem+++{- |+   Defined as '(Data.List.\\)':++   The (\\\\) function is list difference (non-associative). In the result of xs \\\\ ys, the first occurrence of each element of ys in turn (if any) has been removed from xs. Thus (xs <> ys) \\\\ xs == ys.+-}+difference :: (Eq a) => ATC.List a -> ATC.List a -> ATC.List a+difference = (List.\\)+++-- | Defined as '(Data.List.++)'. You could use (Antelude.<>) instead.+combine :: ATC.List a -> ATC.List a -> ATC.List a+combine = (List.++)+++-- | Add an item to the end of a 'List'.+append :: a -> ATC.List a -> ATC.List a+append new lst = combine lst [new]+++-- | Add an item to the beginning of a 'List'.+prepend :: a -> ATC.List a -> ATC.List a+prepend new lst = new : lst+++-- | Defined as 'prepend'. Add an item to the beginning of a 'List'.+cons :: a -> ATC.List a -> ATC.List a+cons = prepend
+ src/Antelude/List/NonEmpty.hs view
@@ -0,0 +1,64 @@+{- |+Module      : Antelude.List.NonEmpty+Description : Contains some functions for NonEmptys, and reexports the Data.List.NonEmpty module.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.List.NonEmpty+    ( -- * Rexports+      module NEExport+      -- * New and Reconstructed for safety+    , append+    , appendList+    , atIndex+    , fromList+    , prepend+    ) where++import safe           Antelude.Function              ( flip, (|>) )+import safe           Antelude.Internal.TypesClasses+    ( Int+    , List+    , Maybe (..)+    , Ordering (..)+    )+import safe           Antelude.List                  as AL ( head )++import safe           Data.List.NonEmpty             as NEExport hiding+    ( append+    , appendList+    , fromList+    )+import safe qualified Data.List.NonEmpty             as NE++import safe           Prelude                        ( Ord (compare) )+++-- | Obtain the element at the given index, starting at 0. 'Nothing' if the index is not valid.+atIndex :: Int -> NonEmpty a -> Maybe a+atIndex index lst = case compare index 0 of+  LT ->+    Nothing+  _ ->+    lst+      |> NE.drop+        index+      |> AL.head+++-- | Convert a `List a` to a `NonEmpty a`+fromList :: List a -> Maybe (NonEmpty a)+fromList = NE.nonEmpty++-- | Add an item to the beginning of a 'NonEmpty'.+prepend :: NonEmpty a -> NonEmpty a -> NonEmpty a+prepend = flip NE.append+++-- | Add an item to the end of a 'NonEmpty'.+append :: NonEmpty a -> NonEmpty a -> NonEmpty a+append = NE.append+++-- | Add a 'List' to the end of a 'NonEmpty'.+appendList :: List a -> NonEmpty a -> NonEmpty a+appendList = flip NE.appendList
+ src/Antelude/Maybe.hs view
@@ -0,0 +1,63 @@+{- |+Module      : Antelude.Maybe+Description : Contains some functions for Maybes.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Maybe+    ( Maybe (..)+      -- | Reexport from 'Data.Maybe'+    , Maybe.isJust+      -- | Reexport from 'Data.Maybe'+    , Maybe.isNothing+    , fromEitherLeft+    , fromEitherRight+    , fromResult+    , map+    , mapWithDefault+    , withDefault+    ) where++import safe           Antelude.Internal.TypesClasses+    ( Either (..)+    , Functor (fmap)+    , Maybe (..)+    , Result (..)+    )++import safe qualified Data.Maybe                     as Maybe+++-- | Defined as 'fmap'. Apply a function to the contents of a 'Maybe', doing nothing if 'Nothing'.+map :: (a -> b) -> Maybe a -> Maybe b+map = fmap+++-- | Get the contents of a 'Maybe', using a default if 'Nothing'.+withDefault :: a -> Maybe a -> a+withDefault = Maybe.fromMaybe+++-- | A combination of 'map'/'fmap' and 'withDefault'. Given a default, a function, and a 'Maybe', get the mapped contents if 'Just', or the default if 'Nothing'.+mapWithDefault :: b -> (a -> b) -> Maybe a -> b+mapWithDefault = Maybe.maybe+++-- | Convert a 'Result a b' to an 'Maybe a', taking the 'Ok' case, or 'Nothing' in the case of 'Err'.+fromResult :: Result err ok -> Maybe ok+fromResult = \case+  Ok ok -> Just ok+  Err _ -> Nothing+++-- | Convert a 'Either a b' to an 'Maybe a', taking the 'Right' case, or 'Nothing' in the case of 'Left'.+fromEitherRight :: Either left right -> Maybe right+fromEitherRight = \case+  Right right -> Just right+  Left _ -> Nothing+++-- | Convert a 'Either a b' to an 'Maybe a', taking the 'Left' case, or 'Nothing' in the case of 'Right'.+fromEitherLeft :: Either left right -> Maybe left+fromEitherLeft = \case+  Left left -> Just left+  Right _ -> Nothing
+ src/Antelude/Monad.hs view
@@ -0,0 +1,18 @@+{- |+Module      : Antelude.Monad+Description : Contains some functions for Monads, and reexports the Control.Monad module.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Monad+    ( module MonadExport+    , ($>)+    , (<<)+    ) where++import safe           Control.Monad as MonadExport++import safe           Data.Functor  ( ($>) )++-- | Just a flipped version of '(>>)'+(<<) :: (Monad m) => m b -> m a -> m b+a << b = b >> a
+ src/Antelude/Numeric.hs view
@@ -0,0 +1,71 @@+{- |+Module      : Antelude.Numeric+Description : Contains some functions for numeric-types.+ Maintainer  : dneavesdev@pm.me+-}+module Antelude.Numeric+    ( P.Double+    , P.Float+    , P.Floating (..)+    , P.Fractional (..)+    , P.Int+    , P.Integer+    , P.Integral (..)+    , P.Num (..)+    , P.Rational+      -- | Reexport from 'Prelude'+    , P.fromIntegral+      -- | Reexport from 'Prelude'+    , P.gcd+      -- | Reexport from 'Prelude'+    , P.lcm+      -- | Reexport from 'Prelude'+    , P.realToFrac+      -- | Reexport from 'Prelude'+    , P.subtract+    , greatestCommonDenominator+    , isEven+    , isOdd+    , leastCommonMultiple+    ) where++import safe           Antelude.Internal.TypesClasses ( Bool, Integral )++import safe qualified Prelude                        as P+    ( Double+    , Float+    , Floating (..)+    , Fractional (..)+    , Int+    , Integer+    , Integral (..)+    , Num (..)+    , Rational+    , even+    , fromIntegral+    , gcd+    , lcm+    , odd+    , realToFrac+    , subtract+    )+++-- | Test if the 'Integral' number is even.+isEven :: (Integral a) => a -> Bool+isEven = P.even+++-- | Test if the 'Integral' number is odd.+isOdd :: (Integral a) => a -> Bool+isOdd = P.odd+++-- | Defined as 'gcd', get the greatest common denominator of two 'Integral' numbers+greatestCommonDenominator :: (Integral a) => a -> a -> a+greatestCommonDenominator = P.gcd+++-- | Defined as 'lcm', get the least common multiple of two 'Integral' numbers+leastCommonMultiple :: (Integral a) => a -> a -> a+leastCommonMultiple = P.lcm
+ src/Antelude/Result.hs view
@@ -0,0 +1,112 @@+{- |+Module      : Antelude.Result+Description : Contains some functions for Results.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Result+    ( Result (..)+    , errWithDefault+    , filterErrs+    , filterOks+    , fromEither+    , fromMaybe+    , isErr+    , isOk+    , mapErr+    , mapOk+    , okWithDefault+    , partition+    , result+    ) where++import safe           Antelude.Function              ( (.>) )+import safe           Antelude.Internal.TypesClasses+    ( Bool (..)+    , Either+    , List+    , Maybe+    , Result (..)+    )+import safe           Antelude.List                  ( foldl' )+import safe           Antelude.Tuple.Pair            ( first, second )++import safe           Prelude                        ( either, maybe, (++) )+++-- | Convert a 'Either a b' to an 'Result a b'.+fromEither :: Either err ok -> Result err ok+fromEither = either Err Ok+++-- | Convert a 'Maybe a' to an 'Result () a'.+fromMaybe :: Maybe ok -> Result () ok+fromMaybe = maybe (Err ()) Ok+++-- | Map both cases of a 'Result a b' given two functions: one for the 'Err' case, and one for the 'Ok' case.+result :: (err -> a) -> (ok -> a) -> Result err ok -> a+result fnErr fnOk = \case+  Ok ok -> fnOk ok+  Err err -> fnErr err+++-- | Map the 'Ok' case of a 'Result a b' given a function. Does not change an 'Err' case.+mapOk :: (ok -> newOk) -> Result err ok -> Result err newOk+mapOk fnOk = result Err (fnOk .> Ok)+++-- | Map the 'Err' case of a 'Result a b' given a function. Does not change an 'Ok' case.+mapErr :: (err -> newErr) -> Result err ok -> Result newErr ok+mapErr fnErr = result (fnErr .> Err) Ok+++-- | Test if the 'Result a b' is 'Ok'.+isOk :: Result err ok -> Bool+isOk = \case+  Ok _ -> True+  Err _ -> False+++-- | Test if the 'Result a b' is 'Err'.+isErr :: Result err ok -> Bool+isErr = \case+  Ok _ -> False+  Err _ -> True+++-- | Get the value of an 'Result a b', returns the 'Ok' value, or a default if 'Err'.+errWithDefault :: ok -> Result err ok -> ok+errWithDefault dflt = \case+  Ok ok -> ok+  Err _ -> dflt+++-- | Get the value of an 'Result a b', returns the 'Err' value, or a default if 'Ok'.+okWithDefault :: err -> Result err ok -> err+okWithDefault dflt = \case+  Ok _ -> dflt+  Err err -> err+++-- | Take a 'List' of 'Result err ok' and create a Tuple with 'List err' and 'List ok'.+partition :: List (Result err ok) -> (List ok, List err)+partition =+  foldl'+    ( \acc res ->+        case res of+          Ok ok ->+            (first acc ++ [ok], second acc)+          Err err ->+            (first acc, second acc ++ [err])+    )+    ([], [])+++-- | Take a 'List' of 'Result a b' and return a 'List' containing all of the values from the 'Ok' cases.+filterOks :: List (Result err ok) -> List ok+filterOks = partition .> first+++-- | Take a 'List' of 'Result a b' and return a 'List' containing all of the values from the 'Err' cases.+filterErrs :: List (Result err ok) -> List err+filterErrs = partition .> second
+ src/Antelude/Sequence.hs view
@@ -0,0 +1,34 @@+{- |+Module      : Antelude.Sequence+Description : Contains some functions for numeric-types.+ Maintainer  : dneavesdev@pm.me+-}+module Antelude.Sequence+    ( module SeqExport+    , append+    , concat+    , prepend+    ) where++import safe           Antelude.Function ( flip )++import safe           Data.Sequence     as SeqExport hiding+    ( index+    , (!?)+    , (<|)+    , (><)+    , (|>)+    )+import safe qualified Data.Sequence     as Seq++-- | Add an element to the left (beginning) of a sequence+prepend :: a -> Seq a -> Seq a+prepend = (Seq.<|)++-- | Add an element to the right (end) of a sequence+append :: a -> Seq a -> Seq a+append = flip (Seq.|>)++-- | Concatenate two sequences+concat :: Seq a -> Seq a -> Seq a+concat = (Seq.><)
+ src/Antelude/String.hs view
@@ -0,0 +1,205 @@+{- |+Module      : Antelude.String+Description : Contains some functions for Strings.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.String+    ( String+    , String.IsString (..)+      -- | Reexport from 'Data.String'+    , String.lines+      -- | Reexport from 'Data.String'+    , String.unlines+      -- | Reexport from 'Data.String'+    , String.unwords+      -- | Reexport from 'Data.String'+    , String.words+    , bytestring+    , bytestringLazy+    , contains+    , join+    , joinWith+    , pad+    , padLeft+    , padRight+    , replace+    , split+    , text+    , textLazy+    , trim+    , trimLeft+    , trimRight+    , unBytestring+    , unBytestringLazy+    , unText+    , unTextLazy+    ) where++import safe           Antelude.Function              ( (|>) )+import safe           Antelude.Internal.TypesClasses+    ( Bool (..)+    , ByteString+    , ByteStringLazy+    , Char+    , Int+    , List+    , String+    , Text+    , TextLazy+    , (<>)+    , (==)+    )+import safe qualified Antelude.List                  as List+import safe           Antelude.Tuple.Pair            ( first )++import safe qualified Data.ByteString.Char8          as BC+import safe qualified Data.ByteString.Lazy.Char8     as BLC+import safe qualified Data.String                    as String+import safe qualified Data.Text                      as TS+import safe qualified Data.Text.Lazy                 as TL+++-- | Given a substring, separate a 'String' into a 'List' containing all parts between (and not including) the substring.+split :: String -> String -> List String+split splitWith splitThis =+    let splitterLength :: Int+        splitterLength = List.length splitWith++        splitFunc :: (List String, String) -> String -> (List String, String)+        splitFunc (accum, []) [] = (accum, [])+        splitFunc (accum, []) tmp = (List.append tmp accum, [])+        splitFunc (accum, str) tmp =+            if List.isPrefixOf splitWith str+            then+                splitFunc+                ( case tmp of+                    "" -> accum+                    _  -> List.append tmp accum+                , List.drop splitterLength str+                )+                []+            else splitFunc (accum, List.drop 1 str) (tmp <> List.take 1 str)+    in  splitFunc ([], splitThis) [] |> first+++-- | Given a "replaceable" substring to replace, and a "replacement" substring, replace all instances of the "replaceable" within a 'String' with the "replacement".+replace :: String -> String -> String -> String+replace _ _ [] = []+replace [] _ string = string+replace replaceThis replaceWith string =+    let replacerLength :: Int+        replacerLength = List.length replaceThis++        replaceFunc :: (List String, String) -> String -> (List String, String)+        replaceFunc (accum, []) [] = (accum, [])+        replaceFunc (accum, []) tmp = (List.append tmp accum, [])+        replaceFunc (accum, str) tmp =+            if List.isPrefixOf replaceThis str+            then+                replaceFunc+                ( List.append (tmp <> replaceWith) accum+                , List.drop replacerLength str+                )+                []+            else replaceFunc (accum, List.drop 1 str) (tmp <> List.take 1 str)+    in  replaceFunc ([], string) [] |> first |> join+++-- | Given a substring, see if it is within a provided 'String'.+contains :: String -> String -> Bool+contains _ [] = False+contains [] _ = True+contains substring string =+    List.isInfixOf substring string+++-- | Join a 'List' of 'String's together with no additional characters+join :: List String -> String+join = List.intercalate ""+++-- | Join a 'List' of 'String's together with a specified character+joinWith :: String -> List String -> String+joinWith = List.intercalate+++-- | Add a specified number of 'Char's to the left side+padLeft :: Int -> Char -> String -> String+padLeft qnt chr str =+    (List.repeat chr |> List.take qnt) <> str+++-- | Add a specified number of 'Char's to the right side+padRight :: Int -> Char -> String -> String+padRight qnt chr str =+    str <> (List.repeat chr |> List.take qnt)+++-- | Add a specified number of 'Char's to the both side+pad :: Int -> Char -> String -> String+pad qnt chr str =+    (List.repeat chr |> List.take qnt) <> str <> (List.repeat chr |> List.take qnt)+++-- | Remove 'Char's from the left+trimLeft :: Char -> String -> String+trimLeft chr str =+    str+        |> List.dropWhile (== chr)+++-- | Remove 'Char's from the right+trimRight :: Char -> String -> String+trimRight chr str =+    str+        |> List.reverse+        |> List.dropWhile (== chr)+        |> List.reverse+++-- | Remove 'Char's from both sides+trim :: Char -> String -> String+trim chr str =+    str+        |> trimRight chr+        |> trimLeft chr+++-- | Turn a String into a strict Text+text :: String -> Text+text = TS.pack+++-- | Turn a strict Text into a String+unText :: Text -> String+unText = TS.unpack+++-- | Turn a String into a lazy Text+textLazy :: String -> TextLazy+textLazy = TL.pack+++-- | Turn a lazy Text into a String+unTextLazy :: TextLazy -> String+unTextLazy = TL.unpack+++-- | Turn a String into a strict ByteString+bytestring :: String -> ByteString+bytestring = BC.pack+++-- | Turn a strict ByteString into a String+unBytestring :: ByteString -> String+unBytestring = BC.unpack+++-- | Turn a String into a lazy ByteString+bytestringLazy :: String -> ByteStringLazy+bytestringLazy = BLC.pack+++-- | Turn a lazy ByteString into a String+unBytestringLazy :: ByteStringLazy -> String+unBytestringLazy = BLC.unpack
+ src/Antelude/String/Case.hs view
@@ -0,0 +1,466 @@+{- |+Module      : Antelude.String.Case+Description : Contains some functions for handling cases for Strings.+Maintainer  : dneavesdev@pm.me+-}+module Antelude.String.Case+    ( Case (..)+      -- * String Deconstruction/Reconstruction+    , buildCase+    , identifyCase+    , recase+    , uncase+      -- * Simple Conversions+    , lowerCase+    , screamingCase+    , titleCase+    ) where++import safe           Antelude.Bool                  ( and, otherwise )+import safe qualified Antelude.Bool                  as Bool ( all )+import safe           Antelude.Function              ( (.>), (|>) )+import safe           Antelude.Internal.TypesClasses+    ( Bool (..)+    , Char+    , Eq+    , List+    , Maybe (..)+    , Ord ((>))+    , Show+    , String+    , (<>)+    )+import safe qualified Antelude.List                  as List+import safe qualified Antelude.Maybe                 as Maybe ( map )+import safe qualified Antelude.String                as String+import safe qualified Antelude.Tuple.Pair            as Pair ( first )++import safe qualified Data.Char                      as Char+    ( isAlpha+    , isAlphaNum+    , isLowerCase+    , isUpperCase+    , toLower+    , toUpper+    )++-- | Convert an entire 'String' to lower case. May be good for preprocessing an ambiguous-case string before 'recase'-ing, but results vary depending on the string.+lowerCase :: String -> String+lowerCase = List.map Char.toLower++-- | Convert an entire 'String' to SCREAMING CASE. May be good for preprocessing an ambiguous-case string before 'recase'-ing, but results vary depending on the string.+screamingCase :: String -> String+screamingCase = List.map Char.toUpper+++-- | Convert an entire 'String' to Title case. Results may vary depending on the string.+titleCase :: String -> String+titleCase string =+    List.uncons string+    |> \case+        Just (head, tail) ->+            [Char.toUpper head] <> List.map Char.toLower tail+        Nothing ->+            string++{- |+A listing of all real and theoretical cases to convert from/to.++For reference:++- sentence cases use spaces like a regular sentence++- snake_cases_use_underscores_between_words++- hyphen-cases-use-hyphens-as-one-would-expect++- dot.cases.use.periods.maybe.useful.for.codegen++- forward\/path\/case\/uses\/forward\/slashes++- back\\path\\case\\uses\\back\\slashes++- camelCase and PascalCase look like these++-}+data Case+    -- sentence cases+    = LowerSentenceCase+    | UpperSentenceCase+    | ScreamingSentenceCase+    | TitleSentenceCase+    -- snake_cases+    | LowerSnakeCase+    | UpperSnakeCase+    | ScreamingSnakeCase+    -- hyphen-cases+    | LowerHyphenCase+    | UpperHyphenCase+    | ScreamingHyphenCase+    -- dot.cases+    | LowerDotCase+    | UpperDotCase+    | ScreamingDotCase+    -- forward/path/case+    | LowerForwardPathCase+    | UpperForwardPathCase+    | ScreamingForwardPathCase+    -- back\path\case+    | LowerBackPathCase+    | UpperBackPathCase+    | ScreamingBackPathCase+    -- camelCases+    | CamelCase+    | PascalCase+    deriving (Eq, Show)+++-- | Identify the 'Case' the 'String' is using+identifyCase :: String -> Maybe Case+identifyCase string =+    let checkSingleCase :: (Char -> Bool) -> String -> String -> Bool+        checkSingleCase func sep str =+            String.contains sep str+                `and`+                    ( String.split sep str+                    |> List.map+                        ( List.filter Char.isAlpha+                        .> List.all func+                        )+                    |> Bool.all+                    )++        checkCapitalCase :: String -> String -> Bool+        checkCapitalCase sep str =+            String.contains sep str+                `and`+                    ( String.split sep str+                    |> List.filter (\s -> List.length s > 0)+                    |> List.map+                        ( List.filter Char.isAlpha+                        .> List.uncons+                        .> \case+                            Just (head, tail) ->+                                Char.isUpperCase head+                                `and`+                                (List.map Char.isLowerCase .> Bool.all) tail+                            Nothing ->+                                True+                        )+                    |> Bool.all+                    )++        checkTitleCase :: String -> String -> Bool+        checkTitleCase sep str =+            String.contains sep str+                `and`+                    ( List.head str+                    |> \case+                        Just head ->+                            Char.isUpperCase head+                        Nothing ->+                            True+                    )+    in+    if  | checkSingleCase Char.isUpperCase " " string+            -> Just ScreamingSentenceCase+        | checkCapitalCase " " string+            -> Just UpperSentenceCase+        | checkSingleCase Char.isLowerCase " " string+            -> Just LowerSentenceCase+        | checkTitleCase " " string+            -> Just TitleSentenceCase+        -- Checks indefinitely from here-on+        | checkSingleCase Char.isUpperCase "-" string+            -> Just ScreamingHyphenCase+        | checkCapitalCase "-" string+            -> Just UpperHyphenCase+        | checkSingleCase Char.isLowerCase "-" string+            -> Just LowerHyphenCase+        | checkSingleCase Char.isUpperCase "_" string+            -> Just ScreamingSnakeCase+        | checkCapitalCase "_" string+            -> Just UpperSnakeCase+        | checkSingleCase Char.isLowerCase "_" string+            -> Just LowerSnakeCase+        | checkSingleCase Char.isUpperCase "." string+            -> Just ScreamingDotCase+        | checkCapitalCase "." string+            -> Just UpperDotCase+        | checkSingleCase Char.isLowerCase "." string+            -> Just LowerDotCase+        | checkSingleCase Char.isUpperCase "/" string+            -> Just ScreamingForwardPathCase+        | checkCapitalCase "/" string+            -> Just UpperForwardPathCase+        | checkSingleCase Char.isLowerCase "/" string+            -> Just LowerForwardPathCase+        | checkSingleCase Char.isUpperCase "\\" string+            -> Just ScreamingBackPathCase+        | checkCapitalCase "\\" string+            -> Just UpperBackPathCase+        | checkSingleCase Char.isLowerCase "\\" string+            -> Just LowerBackPathCase+        | List.all Char.isAlphaNum string+            `and`+                ( List.head+                .> \case+                    Just head -> Char.isLowerCase head+                    Nothing -> False+                ) string+            -> Just CamelCase+        | List.all Char.isAlphaNum string+            `and`+                ( List.head+                .> \case+                    Just head -> Char.isUpperCase head+                    Nothing -> False+                ) string+            -> Just PascalCase+        | otherwise -> Nothing+++data Format+    = Upper+    | Lower+    | Screaming+    -- Specialies+    | Title+    | Pascal+    | Camel+++-- | Construct a 'String' of a desired 'Case' from a 'List' of parts+buildCase :: Case -> List String -> String+buildCase destinationCase parts =+    let joiner :: String+        joiner =+            case destinationCase of+                LowerSnakeCase ->+                    "_"+                UpperSnakeCase ->+                    "_"+                ScreamingSnakeCase ->+                    "_"+                LowerHyphenCase ->+                    "-"+                UpperHyphenCase ->+                    "-"+                ScreamingHyphenCase ->+                    "-"+                LowerSentenceCase ->+                    " "+                UpperSentenceCase ->+                    " "+                ScreamingSentenceCase ->+                    " "+                TitleSentenceCase ->+                    " "+                LowerDotCase ->+                    "."+                UpperDotCase ->+                    "."+                ScreamingDotCase ->+                    "."+                LowerForwardPathCase ->+                    "/"+                UpperForwardPathCase ->+                    "/"+                ScreamingForwardPathCase ->+                    "/"+                LowerBackPathCase ->+                    "\\"+                UpperBackPathCase ->+                    "\\"+                ScreamingBackPathCase ->+                    "\\"+                CamelCase ->+                    ""+                PascalCase ->+                    ""++        format :: Format+        format =+            case destinationCase of+                LowerSnakeCase ->+                    Lower+                UpperSnakeCase ->+                    Upper+                ScreamingSnakeCase ->+                    Screaming+                LowerHyphenCase ->+                    Lower+                UpperHyphenCase ->+                    Upper+                ScreamingHyphenCase ->+                    Screaming+                LowerSentenceCase ->+                    Lower+                UpperSentenceCase ->+                    Upper+                ScreamingSentenceCase ->+                    Screaming+                TitleSentenceCase ->+                    Title+                LowerDotCase ->+                    Lower+                UpperDotCase ->+                    Upper+                ScreamingDotCase ->+                    Screaming+                LowerForwardPathCase ->+                    Lower+                UpperForwardPathCase ->+                    Upper+                ScreamingForwardPathCase ->+                    Screaming+                LowerBackPathCase ->+                    Lower+                UpperBackPathCase ->+                    Upper+                ScreamingBackPathCase ->+                    Screaming+                CamelCase ->+                    Camel+                PascalCase ->+                    Pascal++    in+    case format of+        Upper ->+            List.map+                -- while "titleCase" may look odd here, remember that it's _each word_ being Title-ed+                titleCase+                parts+            |> String.joinWith joiner+        Lower ->+            List.map+                lowerCase+                parts+            |> String.joinWith joiner+        Screaming ->+            List.map+                screamingCase+                parts+            |> String.joinWith joiner+        Title ->+            List.uncons parts+            |> \case+                Just (frst, rest) ->+                    [ titleCase frst+                    ]+                    <> List.map+                        lowerCase+                        rest+                Nothing ->+                    [""]+            |> String.joinWith joiner+        Pascal ->+            List.map+                -- every part of a PascalCase is technically Title-ed+                titleCase+                parts+            |> String.joinWith joiner+        Camel ->+            List.uncons parts+            |> \case+                Just (frst, rest) ->+                    [ lowerCase frst+                    ]+                    <> List.map+                        -- the tail of a camelCase is technically Title-ed+                        titleCase+                        rest+                Nothing ->+                    [""]+            |> String.joinWith joiner++{- | Deconstruct a 'String' by identifying its 'Case'.+    Returns a 'Maybe', in case the case could not be identified.+-}+uncase :: String -> Maybe (List String)+uncase string =+    let oldCase :: Maybe Case+        oldCase = identifyCase string++        folderFunc :: (List String, String) -> (List String, String)+        folderFunc (accm, []) = (accm, [])+        folderFunc (accm, str) =+            let getStr :: String+                getStr =+                    List.take 1 str+                    <>  ( List.drop 1 str+                        |> List.takeWhile Char.isLowerCase+                        )++            in folderFunc (accm <> [getStr], List.drop (List.length getStr) str)++        pascalCamelFolder :: String -> List String+        pascalCamelFolder str =+            folderFunc ([], str)+                |> Pair.first+    in+        Maybe.map+            (\case+                LowerSnakeCase ->+                    String.split "_" string+                UpperSnakeCase ->+                    String.split "_" string+                ScreamingSnakeCase ->+                    String.split "_" string+                LowerHyphenCase ->+                    String.split "-" string+                UpperHyphenCase ->+                    String.split "-" string+                ScreamingHyphenCase ->+                    String.split "-" string+                LowerSentenceCase ->+                    String.split " " string+                UpperSentenceCase ->+                    String.split " " string+                ScreamingSentenceCase ->+                    String.split " " string+                TitleSentenceCase ->+                    String.split " " string+                LowerDotCase ->+                    String.split "." string+                UpperDotCase ->+                    String.split "." string+                ScreamingDotCase ->+                    String.split "." string+                LowerForwardPathCase ->+                    String.split "/" string+                UpperForwardPathCase ->+                    String.split "/" string+                ScreamingForwardPathCase ->+                    String.split "/" string+                LowerBackPathCase ->+                    String.split "\\" string+                UpperBackPathCase ->+                    String.split "\\" string+                ScreamingBackPathCase ->+                    String.split "\\" string+                CamelCase ->+                    let firstWord :: String+                        firstWord =+                            List.takeWhile Char.isLowerCase string++                        restOfWords :: List String+                        restOfWords =+                            string+                                |> List.drop (List.length firstWord)+                                |> pascalCamelFolder+                    in+                    [firstWord] <> restOfWords+                PascalCase ->+                    pascalCamelFolder string+            )+            oldCase++{- | Given a desired 'Case' and a 'String', try and convert to the given 'Case'.+    Returns a 'Maybe', in case the original case could not be identified.+-}+recase :: Case -> String -> Maybe String+recase destinationCase string =+    uncase string+    |> Maybe.map (buildCase destinationCase)
+ src/Antelude/Tuple/Pair.hs view
@@ -0,0 +1,50 @@+{- |+Module      : Antelude.Tuple.Pair+Description : Contains some functions for a two-member Tuple (a Pair).+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Tuple.Pair+    ( Pair+    , curry+    , first+    , mapFirst+    , mapSecond+    , pack+    , second+    , swap+    , uncurry+    ) where++import safe           Antelude.Internal.TypesClasses ( Pair )++import safe           Data.Tuple                     ( curry, uncurry )+++-- | Get the first item of a 'Pair' Tuple+first :: Pair a b -> a+first (a, _) = a+++-- | Get the second item of a 'Pair' Tuple+second :: Pair a b -> b+second (_, b) = b+++-- | Apply a function to the first item of a 'Pair' Tuple+mapFirst :: (a -> z) -> Pair a b -> Pair z b+mapFirst fn (a, b) = (fn a, b)+++-- | Apply a function to the second item of a 'Pair' Tuple+mapSecond :: (b -> z) -> Pair a b -> Pair a z+mapSecond fn (a, b) = (a, fn b)+++-- | Swap the items in a 'Pair' Tuple+swap :: Pair a b -> Pair b a+swap (a, b) = (b, a)+++-- | Pack both arguments into a 'Pair' Tuple+pack :: a -> b -> Pair a b+pack a b = (a, b)
+ src/Antelude/Tuple/Trio.hs view
@@ -0,0 +1,86 @@+{- |+Module      : Antelude.Tuple.Trio+Description : Contains some functions for a three-member Tuple (a Trio).+Maintainer  : dneavesdev@pm.me+-}+module Antelude.Tuple.Trio+    ( Trio+    , curry+    , cycleCCW+    , cycleCW+    , first+    , mapFirst+    , mapSecond+    , mapThird+    , pack+    , reverse+    , second+    , third+    , uncurry+    ) where++import safe           Antelude.Internal.TypesClasses ( Trio )+++-- | Get the first item of a 'Trio' Tuple+first :: Trio a b c -> a+first (a, _, _) = a+++-- | Get the second item of a 'Trio' Tuple+second :: Trio a b c -> b+second (_, b, _) = b+++-- | Get the third item of a 'Trio' Tuple+third :: Trio a b c -> c+third (_, _, c) = c+++-- | Apply a function to the first item of a 'Trio' Tuple+mapFirst :: (a -> z) -> Trio a b c -> Trio z b c+mapFirst fn (a, b, c) = (fn a, b, c)+++-- | Apply a function to the second item of a 'Trio' Tuple+mapSecond :: (b -> z) -> Trio a b c -> Trio a z c+mapSecond fn (a, b, c) = (a, fn b, c)+++-- | Apply a function to the third item of a 'Trio' Tuple+mapThird :: (c -> z) -> Trio a b c -> Trio a b z+mapThird fn (a, b, c) = (a, b, fn c)+++{- |+   Rotates the item of a 'Trio' Tuple, moving to the right.+   The last item loops back to the first+-}+cycleCW :: Trio a b c -> Trio c a b+cycleCW (a, b, c) = (c, a, b)+++{- |+   Rotates the item of a 'Trio' Tuple, moving to the left.+   The first item loops back to the last+-}+cycleCCW :: Trio a b c -> Trio b c a+cycleCCW (a, b, c) = (b, c, a)+++-- | Flip the 'Trio' Tuple around, so the first becomes the last and vice versa.+reverse :: Trio a b c -> Trio c b a+reverse (a, b, c) = (c, b, a)+++-- | Pack all three arguments into a 'Trio' Tuple+pack :: a -> b -> c -> Trio a b c+pack a b c = (a, b, c)++-- | convert an uncurried function into a curried function+curry :: ((a, b, c) -> d) -> a -> b -> c -> d+curry fn a b c = fn (a, b, c)++-- | convert a curried function to a function on a 'Trio'+uncurry :: (a -> b -> c -> d) -> (a, b, c) -> d+uncurry fn (a, b, c) = fn a b c
+ test/Main.hs view
@@ -0,0 +1,293 @@+module Main+    ( main+    ) where++import safe           Antelude+import safe qualified Antelude.Array         as AArray+import safe qualified Antelude.Bool          as ABool+import safe qualified Antelude.Either        as AEither+import safe qualified Antelude.Function      as AFunction+import safe qualified Antelude.List          as AList+import safe qualified Antelude.List.NonEmpty as ANonEmpty+import safe qualified Antelude.Maybe         as AMaybe+import safe qualified Antelude.Result        as AResult+import safe qualified Antelude.String        as AString+import safe qualified Antelude.String.Case   as ACase+import safe qualified Antelude.Tuple.Pair    as APair+import safe qualified Antelude.Tuple.Trio    as ATrio++import safe           Test.HUnit+    ( Test (..)+    , assertEqual+    , runTestTTAndExit+    )+++main :: IO ()+main = runTestTTAndExit tests+++-- https://hackage.haskell.org/package/HUnit+tests :: Test+tests =+  TestList+    [ testArray+    , testBool+    , testEither+    , testFunction+    , testList+    , testMaybe+    , testMonad+    , testNonEmpty+    , testResult+    , testString+    , testStringCase+    , testTuplesPair+    , testTuplesTrio+    , testAnteludeBase+    ]+++-- A lot of the contents are just renames, only test what isn't a rename+testArray :: Test+testArray =+  TestList+    [ TestCase (assertEqual "array from nonempty" (AArray.array (1, 1) [(1, "1")] :: Array Int String) (AArray.fromNonEmpty (1, 1) ("1" ANonEmpty.:| [])))+    , TestCase (assertEqual "array update" (AArray.array (1, 1) [(1, "1")] :: Array Int String) (AArray.update [(1, "1")] (AArray.array (1, 1) [(1, "0")] :: Array Int String)))+    , TestCase (assertEqual "array at index 1" (Just "1") (AArray.atIndex 1 (AArray.array (1, 1) [(1, "1")] :: Array Int String)))+    , TestCase (assertEqual "array at index 2" Nothing (AArray.atIndex 2 (AArray.array (1, 1) [(1, "1")] :: Array Int String)))+    , TestCase (assertEqual "array at index 3" Nothing (AArray.atIndex 0 (AArray.array (1, 1) [(1, "1")] :: Array Int String)))+    ]+++testBool :: Test+testBool =+  TestList+    [ TestCase (assertEqual "bool word and" True (True `ABool.and` True))+    , TestCase (assertEqual "bool word or" True (True `ABool.or` True))+    , TestCase (assertEqual "bool word xor" True (True `ABool.xor` False))+    ]+++testEither :: Test+testEither =+  TestList+    [ TestCase (assertEqual "either from result 1" (Right "string") (AEither.fromResult (Ok "string") :: Either String String))+    , TestCase (assertEqual "either from result 2" (Left "string") (AEither.fromResult (Err "string") :: Either String String))+    , TestCase (assertEqual "either from maybe 1" (Right "string") (AEither.fromMaybe (Just "string")))+    , TestCase (assertEqual "either from maybe 2" (Left ()) (AEither.fromMaybe Nothing :: Either () String))+    , TestCase (assertEqual "either map left maps left" (Left "hello world") (AEither.mapLeft (<> " world") (Left "hello") :: Either String String))+    , TestCase (assertEqual "either map left ignores right" (Right "hello") (AEither.mapLeft (<> " world") (Right "hello") :: Either String String))+    , TestCase (assertEqual "either map right maps right" (Right "hello world") (AEither.mapRight (<> " world") (Right "hello") :: Either String String))+    , TestCase (assertEqual "either map right ignores left" (Left "hello") (AEither.mapRight (<> " world") (Left "hello") :: Either String String))+    , TestCase (assertEqual "either swap 1" (Right 0) (AEither.swap (Left 0) :: Either Int Int))+    , TestCase (assertEqual "either swap 2" (Left 0) (AEither.swap (Right 0) :: Either Int Int))+    , TestCase (assertEqual "either left with default 1" "left" (AEither.leftWithDefault "default" (Left "left" :: Either String String)))+    , TestCase (assertEqual "either left with default 2" "default" (AEither.leftWithDefault "default" (Right "right" :: Either String String)))+    , TestCase (assertEqual "either right with default 1" "right" (AEither.rightWithDefault "default" (Right "right" :: Either String String)))+    , TestCase (assertEqual "either right with default 2" "default" (AEither.rightWithDefault "default" (Left "left" :: Either String String)))+    , TestCase (assertEqual "either filter lefts" ["1", "3"] (AEither.filterLefts [Left "1", Right "2", Left "3", Right "4"]))+    , TestCase (assertEqual "either filter rights" ["2", "4"] (AEither.filterRights [Left "1", Right "2", Left "3", Right "4"]))+    , TestCase (assertEqual "either partition" (["1", "3"], ["2", "4"]) (AEither.partition [Left "1", Right "2", Left "3", Right "4"]))+    ]+++testFunction :: Test+testFunction =+  TestList+    [ TestCase (assertEqual "function identity" "string" (AFunction.identity "string"))+    , TestCase (assertEqual "function constant" "always" (AFunction.constant "always" "never"))+    , TestCase (assertEqual "function flip" "hello world" (AFunction.flip (<>) "world" "hello "))+    , TestCase (assertEqual "function left arrow" "left arrow" (AFunction.identity <| "left arrow"))+    , TestCase (assertEqual "function right arrow" "right arrow" ("right arrow" |> AFunction.identity))+    , TestCase (assertEqual "function left compose" "composed" ((AFunction.identity <. AFunction.identity) "composed"))+    , TestCase (assertEqual "function right compose" "composed" ((AFunction.identity .> AFunction.identity) "composed"))+    ]+++testList :: Test+testList =+  TestList+    [ TestCase (assertEqual "list head 1" (Just "1") (AList.head ["1", "2", "3"]))+    , TestCase (assertEqual "list head 2" Nothing (AList.head ([] :: List String)))+    , TestCase (assertEqual "list last 1" (Just "3") (AList.last ["1", "2", "3"]))+    , TestCase (assertEqual "list last 2" Nothing (AList.last ([] :: List String)))+    , TestCase (assertEqual "list tail 1" (Just ["2", "3"]) (AList.tail ["1", "2", "3"]))+    , TestCase (assertEqual "list tail 2" Nothing (AList.tail ([] :: List String)))+    , TestCase (assertEqual "list init 1" (Just ["1", "2"]) (AList.init ["1", "2", "3"]))+    , TestCase (assertEqual "list init 2" Nothing (AList.init ([] :: List String)))+    , TestCase (assertEqual "list at index 1" (Just "1") (AList.atIndex 0 ["1", "2", "3"]))+    , TestCase (assertEqual "list at index 2" Nothing (AList.atIndex (-1) ["1", "2", "3"]))+    , TestCase (assertEqual "list at index 3" Nothing (AList.atIndex 3 ["1", "2", "3"]))+    , TestCase (assertEqual "list at index 4" Nothing (AList.atIndex (-4) ["1", "2", "3"]))+    , TestCase (assertEqual "list append" ["1", "2", "3"] (AList.append "3" ["1", "2"]))+    , TestCase (assertEqual "list prepend" ["1", "2", "3"] (AList.prepend "1" ["2", "3"]))+    , TestCase (assertEqual "list cons" ["1", "2", "3"] (AList.cons "1" ["2", "3"]))+    ]+++testMaybe :: Test+testMaybe =+  TestList+    [ TestCase (assertEqual "maybe map 1" (Just "hello world") (AMaybe.map (<> " world") (Just "hello")))+    , TestCase (assertEqual "maybe map 2" Nothing (AMaybe.map (<> " world") Nothing))+    , TestCase (assertEqual "maybe with default 1" "just" (AMaybe.withDefault "default" (Just "just")))+    , TestCase (assertEqual "maybe with default 2" "default" (AMaybe.withDefault "default" Nothing))+    , TestCase (assertEqual "maybe from result 1" (Just "ok") (AMaybe.fromResult (Ok "ok")))+    , TestCase (assertEqual "maybe from result 2" Nothing (AMaybe.fromResult (Err "err" :: Result String String)))+    , TestCase (assertEqual "maybe from either right 1" (Just "right") (AMaybe.fromEitherRight (Right "right" :: Either String String)))+    , TestCase (assertEqual "maybe from either right 2" Nothing (AMaybe.fromEitherRight (Left "left" :: Either String String)))+    , TestCase (assertEqual "maybe from either left 1" (Just "left") (AMaybe.fromEitherLeft (Left "left" :: Either String String)))+    , TestCase (assertEqual "maybe from either left 2" Nothing (AMaybe.fromEitherLeft (Right "right" :: Either String String)))+    ]+++testMonad :: Test+testMonad =+  TestList+    [ TestCase (assertEqual "monad left doublepointy" (Just "a string") (Just "a string" << Just "nope"))+    ]+++testNonEmpty :: Test+testNonEmpty =+  TestList+    [ TestCase (assertEqual "nonempty prepend" ("1" :| ["2", "3"]) (ANonEmpty.prepend ("2" :| ["3"]) ("1" :| [])))+    , TestCase (assertEqual "nonempty append" ("2" :| ["3", "1"]) (ANonEmpty.append ("2" :| ["3"]) ("1" :| [])))+    , TestCase (assertEqual "nonempty appendList" ("2" :| ["3", "1"]) (ANonEmpty.appendList ["1"] ("2" :| ["3"])))+    , TestCase (assertEqual "nonempty at index 1" (Just "1") (ANonEmpty.atIndex 0 ("1" :| ["2", "3"])))+    , TestCase (assertEqual "nonempty at index 2" Nothing (ANonEmpty.atIndex (-2) ("1" :| ["2", "3"])))+    , TestCase (assertEqual "nonempty at index 3" (Just "3") (ANonEmpty.atIndex 2 ("1" :| ["2", "3"])))+    , TestCase (assertEqual "nonempty at index 4" Nothing (ANonEmpty.atIndex 5 ("1" :| ["2", "3"])))+    , TestCase (assertEqual "nonempty at index 5" Nothing (ANonEmpty.atIndex (-5) ("1" :| ["2", "3"])))+    -- Only in base 4.21, comment cause flaky on old versions+    -- , TestCase (assertEqual "nonempty sort on" ('1' :| ['2', '3', '4']) (ANonEmpty.sortOn Char.ord ('3' :| ['4', '2', '1'])))+    ]+++testResult :: Test+testResult =+  TestList+    [ TestCase (assertEqual "result from either 1" (Ok "ok") (AResult.fromEither (Right "ok" :: Either String String)))+    , TestCase (assertEqual "result from either 2" (Err "ok") (AResult.fromEither (Left "ok" :: Either String String)))+    , TestCase (assertEqual "result from maybe 1" (Ok "this") (AResult.fromMaybe (Just "this")))+    , TestCase (assertEqual "result from maybe 2" (Err () :: Result () String) (AResult.fromMaybe Nothing))+    , TestCase (assertEqual "result result 1" "this is ok" (AResult.result (<> " is an err") (<> " is ok") (Ok "this")))+    , TestCase (assertEqual "result result 2" "this is an err" (AResult.result (<> " is an err") (<> " is ok") (Err "this")))+    , TestCase (assertEqual "result map ok 1" (Ok "hello world") (AResult.mapOk (<> " world") (Ok "hello") :: Result String String))+    , TestCase (assertEqual "result map ok 2" (Err "hello") (AResult.mapOk (<> " world") (Err "hello") :: Result String String))+    , TestCase (assertEqual "result map err 1" (Err "hello world") (AResult.mapErr (<> " world") (Err "hello") :: Result String String))+    , TestCase (assertEqual "result map err 2" (Ok "hello") (AResult.mapErr (<> " world") (Ok "hello") :: Result String String))+    , TestCase (assertEqual "result is ok 1" True (AResult.isOk (Ok "this")))+    , TestCase (assertEqual "result is ok 2" False (AResult.isOk (Err "this")))+    , TestCase (assertEqual "result is err 1" False (AResult.isErr (Ok "this")))+    , TestCase (assertEqual "result is err 2" True (AResult.isErr (Err "this")))+    , TestCase (assertEqual "result with default err 1" "ok" (AResult.errWithDefault "default" (Ok "ok")))+    , TestCase (assertEqual "result with default err 2" "default" (AResult.errWithDefault "default" (Err "err")))+    , TestCase (assertEqual "result with default ok 1" "default" (AResult.okWithDefault "default" (Ok "ok")))+    , TestCase (assertEqual "result with default ok 2" "err" (AResult.okWithDefault "default" (Err "err")))+    , TestCase (assertEqual "result filter ok" ["1", "3"] (AResult.filterOks [Ok "1", Err "2", Ok "3", Err "4"]))+    , TestCase (assertEqual "result filter err" ["2", "4"] (AResult.filterErrs [Ok "1", Err "2", Ok "3", Err "4"]))+    , TestCase (assertEqual "result filter err" (["1", "3"], ["2", "4"]) (AResult.partition [Ok "1", Err "2", Ok "3", Err "4"]))+    ]+++testString :: Test+testString =+  TestList+    [ TestCase (assertEqual "string split 1" ["00", "01", "10", "11"] (AString.split "--" "00--01--10--11"))+    , TestCase (assertEqual "string split 2" ["00", "01"] (AString.split "--" "00--01--"))+    , TestCase (assertEqual "string split 3" ["00", "01"] (AString.split "--" "--00--01"))+    , TestCase (assertEqual "string split 4" ["-00", "-01-"] (AString.split "--" "-00---01-"))+    , TestCase (assertEqual "string replace 1" "this sentence is fixed" (AString.replace "{replace me}" "fixed" "this sentence is {replace me}"))+    , TestCase (assertEqual "string replace 2" "" (AString.replace "{replace me}" "fixed" ""))+    , TestCase (assertEqual "string replace 3" "this sentence is {replace me}" (AString.replace "" "fixed" "this sentence is {replace me}"))+    , TestCase (assertEqual "string replace 4" "this sentence is " (AString.replace "{replace me}" "" "this sentence is {replace me}"))+    , TestCase (assertEqual "string replace 5" "this sentence is fixed" (AString.replace "{replace me}" "this" "{replace me} sentence is fixed"))+    ]++testStringCase :: Test+testStringCase =+    TestList+        [ TestCase (assertEqual "case identify screaming sentence" (Just ACase.ScreamingSentenceCase) (ACase.identifyCase "SCREAMING SENTENCE"))+        , TestCase (assertEqual "case identify upper sentence" (Just ACase.UpperSentenceCase) (ACase.identifyCase "Upper Sentence"))+        , TestCase (assertEqual "case identify title sentence" (Just ACase.TitleSentenceCase) (ACase.identifyCase "Title sentence"))+        , TestCase (assertEqual "case identify lower sentence" (Just ACase.LowerSentenceCase) (ACase.identifyCase "lower sentence"))+        , TestCase (assertEqual "case identify screaming hyphen" (Just ACase.ScreamingHyphenCase) (ACase.identifyCase "SCREAMING-HYPHEN"))+        , TestCase (assertEqual "case identify upper hyphen" (Just ACase.UpperHyphenCase) (ACase.identifyCase "Upper-Hyphen"))+        , TestCase (assertEqual "case identify lower hyphen" (Just ACase.LowerHyphenCase) (ACase.identifyCase "lower-hyphen"))+        , TestCase (assertEqual "case identify screaming snake" (Just ACase.ScreamingSnakeCase) (ACase.identifyCase "SCREAMING_SNAKE"))+        , TestCase (assertEqual "case identify upper snake" (Just ACase.UpperSnakeCase) (ACase.identifyCase "Upper_Snake"))+        , TestCase (assertEqual "case identify lower snake" (Just ACase.LowerSnakeCase) (ACase.identifyCase "lower_snake"))+        , TestCase (assertEqual "case identify screaming dot" (Just ACase.ScreamingDotCase) (ACase.identifyCase "SCREAMING.DOT"))+        , TestCase (assertEqual "case identify upper dot" (Just ACase.UpperDotCase) (ACase.identifyCase "Upper.Dot"))+        , TestCase (assertEqual "case identify lower dot" (Just ACase.LowerDotCase) (ACase.identifyCase "lower.dot"))+        , TestCase (assertEqual "case identify screaming fpath" (Just ACase.ScreamingForwardPathCase) (ACase.identifyCase "SCREAMING/FORWARD/PATH"))+        , TestCase (assertEqual "case identify upper fpath" (Just ACase.UpperForwardPathCase) (ACase.identifyCase "Upper/Forward/Path"))+        , TestCase (assertEqual "case identify lower fpath" (Just ACase.LowerForwardPathCase) (ACase.identifyCase "lower/forward/path"))+        , TestCase (assertEqual "case identify screaming bpath" (Just ACase.ScreamingBackPathCase) (ACase.identifyCase "SCREAMING\\BACK\\PATH"))+        , TestCase (assertEqual "case identify upper bpath" (Just ACase.UpperBackPathCase) (ACase.identifyCase "Upper\\Back\\Path"))+        , TestCase (assertEqual "case identify lower bpath" (Just ACase.LowerBackPathCase) (ACase.identifyCase "lower\\back\\path"))+        , TestCase (assertEqual "case identify pascal" (Just ACase.PascalCase) (ACase.identifyCase "PascalCase"))+        , TestCase (assertEqual "case identify camel" (Just ACase.CamelCase) (ACase.identifyCase "camelCase"))+        , TestCase (assertEqual "case identify indeterminate" Nothing (ACase.identifyCase "123456789"))+        , TestCase (assertEqual "case recase screaming sentence" (Just "SCREAMING SENTENCE") (ACase.recase ACase.ScreamingSentenceCase "screaming sentence"))+        , TestCase (assertEqual "case recase upper sentence" (Just "Upper Sentence") (ACase.recase ACase.UpperSentenceCase "UPPER_SENTENCE"))+        , TestCase (assertEqual "case recase title sentence" (Just "Title sentence") (ACase.recase ACase.TitleSentenceCase "TitleSentence"))+        , TestCase (assertEqual "case recase lower sentence" (Just "lower sentence") (ACase.recase ACase.LowerSentenceCase "Lower.Sentence"))+        , TestCase (assertEqual "case recase screaming hyphen" (Just "SCREAMING-HYPHEN") (ACase.recase ACase.ScreamingHyphenCase "Screaming Hyphen"))+        , TestCase (assertEqual "case recase upper hyphen" (Just "Upper-Hyphen") (ACase.recase ACase.UpperHyphenCase "upper/hyphen"))+        , TestCase (assertEqual "case recase lower hyphen" (Just "lower-hyphen") (ACase.recase ACase.LowerHyphenCase "LOWER\\HYPHEN"))+        , TestCase (assertEqual "case recase screaming snake" (Just "SCREAMING_SNAKE") (ACase.recase ACase.ScreamingSnakeCase "ScreamingSnake"))+        , TestCase (assertEqual "case recase upper snake" (Just "Upper_Snake") (ACase.recase ACase.UpperSnakeCase "upper.snake"))+        , TestCase (assertEqual "case recase lower snake" (Just "lower_snake") (ACase.recase ACase.LowerSnakeCase "LOWER/SNAKE"))+        , TestCase (assertEqual "case recase screaming dot" (Just "SCREAMING.DOT") (ACase.recase ACase.ScreamingDotCase "Screaming_Dot"))+        , TestCase (assertEqual "case recase upper dot" (Just "Upper.Dot") (ACase.recase ACase.UpperDotCase "Upper dot"))+        , TestCase (assertEqual "case recase lower dot" (Just "lower.dot") (ACase.recase ACase.LowerDotCase "lower.dot"))+        , TestCase (assertEqual "case recase screaming fpath" (Just "SCREAMING/FORWARD/PATH") (ACase.recase ACase.ScreamingForwardPathCase "SCREAMING-FORWARD-PATH"))+        , TestCase (assertEqual "case recase upper fpath" (Just "Upper/Forward/Path") (ACase.recase ACase.UpperForwardPathCase "upper/forward/path"))+        , TestCase (assertEqual "case recase lower fpath" (Just "lower/forward/path") (ACase.recase ACase.LowerForwardPathCase "Lower forward path"))+        , TestCase (assertEqual "case recase screaming bpath" (Just "SCREAMING\\BACK\\PATH") (ACase.recase ACase.ScreamingBackPathCase "screaming.back.path"))+        , TestCase (assertEqual "case recase upper bpath" (Just "Upper\\Back\\Path") (ACase.recase ACase.UpperBackPathCase "upper_back_path"))+        , TestCase (assertEqual "case recase lower bpath" (Just "lower\\back\\path") (ACase.recase ACase.LowerBackPathCase "LOWER BACK PATH"))+        , TestCase (assertEqual "case recase pascal" (Just "PascalCase") (ACase.recase ACase.PascalCase "pascalCase"))+        , TestCase (assertEqual "case recase camel" (Just "camelCase") (ACase.recase ACase.CamelCase "Camel-Case"))+        , TestCase (assertEqual "case recase indeterminate" Nothing (ACase.recase ACase.UpperDotCase "123456789"))+        -- No need to test 'uncase' or 'buildCase', it's clearly working in 'recase'.+        -- Technically don't even need to test 'identifyCase', but why not.+        ]+++testTuplesPair :: Test+testTuplesPair =+  TestList+    [ TestCase (assertEqual "tuple pair first" "1" (APair.first ("1", "2")))+    , TestCase (assertEqual "tuple pair second" "2" (APair.second ("1", "2")))+    , TestCase (assertEqual "tuple pair map first" ("13", "2") (APair.mapFirst (<> "3") ("1", "2")))+    , TestCase (assertEqual "tuple pair map second" ("1", "23") (APair.mapSecond (<> "3") ("1", "2")))+    , TestCase (assertEqual "tuple pair swap" ("2", "1") (APair.swap ("1", "2")))+    , TestCase (assertEqual "tuple pair pack" ("1", "2") (APair.pack "1" "2"))+    ]+++testTuplesTrio :: Test+testTuplesTrio =+  TestList+    [ TestCase (assertEqual "tuple trio first" "1" (ATrio.first ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio second" "2" (ATrio.second ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio third" "3" (ATrio.third ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio map first" ("14", "2", "3") (ATrio.mapFirst (<> "4") ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio map second" ("1", "24", "3") (ATrio.mapSecond (<> "4") ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio map third" ("1", "2", "34") (ATrio.mapThird (<> "4") ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio cycle clockwise" ("3", "1", "2") (ATrio.cycleCW ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio cycle counterclockwise" ("2", "3", "1") (ATrio.cycleCCW ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio reverse" ("3", "2", "1") (ATrio.reverse ("1", "2", "3")))+    , TestCase (assertEqual "tuple trio pack" ("1", "2", "3") (ATrio.pack "1" "2" "3"))+    ]+++testAnteludeBase :: Test+testAnteludeBase =+  TestList+    [ TestCase (assertEqual "" () ())+    ]