README.md

Antelude #

antelude logo. please excuse my non-graphic-designer graphic-design

Yet another alternative Prelude for Haskell.

https://english.stackexchange.com/questions/554704/difference-between-the-prefixes-pre-and-ante :

  • ante (w/acc) > location and direction (ante + chamber = before the room, --> towards it) whereas > (ante + mortem = before death <-- prior to it)
  • prae (w/abl) > place where = position (pre + fer = put before --above all)

Motivation #

I came into Haskell from learning Elm, enjoying Elm, and wanting a familiar way of programming for backend-type code. While Haskell is one of the closest relatives (syntax/style-wise, obviously not in purpose), there are parts that are very different and were at-first confusing. NRI made a prelude that mimics closely things Elm developers may be familiar with, to ease them into it, and fix up some of the standard Prelude where applicable: NRI Prelude

On the other hand, I had also come across Relude. Compared to the NRI-Prelude, Relude tries to keep things familiar for the existing Haskell developers, while also doing its own opinionated fixing of some of the flaws of the standard Prelude.

While these are both great options (and there are also others out there!), I began to have ideas on how I wanted to work with Haskell. And a large portion of the time, the way one gets exactly what they want is by doing it themselves.

Hence, yet another Prelude. But, the "yet another x" naming convention has run its course in my mind, so this was not going to be Yaprelude, Yalude, or anything of the sorts. Instead, wordplay of the prefix "Pre-". Thus: Ante-lude.

Important changes! #

Here's a good chunk of notable changes:

  • (.) is not natively available in Antelude, allowing for clarity when using the OverloadedRecordDot language extension. If you need the backwards-function-composition behavior of Prelude's (.), see (<.) (and its forwards-pointed counterpart, (.>))
  • ($) is not natively available in Antelude. Please see (<|) (and its forward-pointed counterpart (|>))
    • Antelude's ((<|), (|>)) is not the same as in Data.Sequence. Antelude.Sequence gives these symbols textual function names in case you were looking to use Data.Sequence.((<|), (|>)).
  • (++) is not natively available in Antelude. It's only purpose is to concatonate two lists, which (<>) can also do. If (<>) is not sufficient, Antelude.List.combine is defined as (Data.List.++)
    • I have identified an issue when using cabal's Paths_ modules. To remedy this, you can use the "making your own Prelude" method below (Installing/Using), importing Data.List.(++) and exposing it.
  • Antelude.Bool.(all, any) are equivalent to Prelude.(and, or). However, Antelude.List.(all, any) are the same as Prelude.(all, any).
  • Antelude.List.(head, tail, init, last) return Maybe's and are safe for use. You can get the original ones from Data.List, but you shouldn't.
  • fst, snd are not available. Tuples.Pair has first, second, and Tuples.Trio has first, second, third, as well as other Tuple tools for their bunch. If you really need fst, snd instead of their full-name counterparts, get them from Data.Tuple
  • Almost everything has been moved into some Antelude module. Please take a look to see where to find what you were expecting to be in the global scope.

I purposely tried to restrict what is in the global scope. Most items are contained within Antelude.___ modules, or should be found from their native Data/Control.___ modules. This is an all inclusive list of functions that are in the global scope:

(|>)* (<|)* (.>) (<.) (<$>) (<&>)
(<*>) (<*) (*>) (<|>) (<>) ($!)
(<$) ($>) (&&) (||) (:|) (+)
(-) (*) (**) (/) (^) (^^)
(>) (<) (>=) (<=) (==) (/=)
(>>=) (=<<) (>>) (<<) (>=>) (<=<)
fmap liftA2 empty liftIO show showList
print otherwise pure return

*Notes:

  • Remember, (<|), (|>) are not the same as from Data.Sequence.

...as well as the following types:

Bool(..) Char String Int Integer
Float Double Rational Word List a*
NonEmpty a Array i a Pair a b* Trio a b c* Seq a
Text* TextLazy* ByteString* ByteStringLazy* Set a
Map a b* MapLazy a b* Maybe(..) Either(..) Result(..)
Ordering(..) ShowS ReadS a IO a IOError
FilePath Void

*Notes:

  • List a is just an alias to [a]
    • base 4.21 now has this same alias.
    • I'll have to figure out how to use that one and not ours so it works.
  • Pair a b is just an alias to (a, b)
  • Trio a b c is just an alias to (a, b, c)
  • Text is equivalent to Data.Text (Text)
  • TextLazy is equivalent to Data.Text.Lazy (Text)
  • ByteString is equivalent to Data.ByteString (ByteString)
  • ByteStringLazy is equivalent to Data.ByteString.Lazy (ByteString)
  • Map a b is equivalent to Data.Map.Strict (Map)
  • MapLazy a b is equivalent to Data.Map (Map)

...and typeclasses (to see which methods are exported from these typeclasses, see the exposed functions table above):

Eq Ord Enum Bounded Num
Real Integral Fractional Floating RealFrac
RealFloat Semigroup Monoid Functor Applicative
Alternative Monad MonadIO MonadPlus MonadFail
Foldable Traversable Show Read

I encourage qualified imports, or named imports at the very least, as it helps newer developers understand where something came from and also helps solve name-conflict issues.

Between 0.1.0 and 1.0.0, things may change. Most probably won't, but some might. We'll see.

To-Do's #

  • Decide if INLINE-ing is needed or wanted, and if so, where.
  • Decide if Antelude's modules feel "feature complete".
  • Maybe making Antelude backwards-compatible, where reasonable.

Installing/Using #

All of these involve adding Antelude as a dependency. So start with that, then...

using Cabal mixins, you should be able to do this in your library/executable/etc:

  mixins:   base hiding (Prelude)
          , antelude (Antelude as Prelude)
          , antelude

stack's mixin version will be listed when I get this on Stackage, but it's something like found here

Or for a build-tool agnostic verison, you can try making your own Prelude.hs next to your Main.hs file:

  app/              <- a directory you defined in "hs-source-dirs" where...
    Main.hs         <- your "main-is" file (if an executable).
    Prelude.hs      <- add this, then see Prelude snippet below.
  yourProject.cabal
  stack.yaml
module Prelude
    ( module Antelude
    ) where

import Antelude