{- | Overture is an alternative to some of the "Prelude". It aims to make Haskell easier to read by providing a few well-named functions and operators. Overture does not export anything that conflicts with the "Prelude". Whenever possible, it tries not to conflict with any other well-known packages. The recommended way to use Overture is to import it unqualified. >>> import Overture == Motivation I have been using Haskell for more than I year. In that time, I created libraries and executables. I deployed Haskell to production at my day job. I wrote several blog posts about Haskell. All this to say that I'm not a complete beginner. Yet I sometimes have trouble undestanding Haskell code. Usually function composition and pointfree expressions are to blame. To me, they read backwards. Take this function for example. >>> let f = negate . recip . succ Is it immediately obvious to you what this does? If so, this package probably isn't for you. For me, I start reading "negate" before I realize that this is a chain of composed functions, which means I have to start at the end. Eventually I end up understanding that this function adds one, then takes the reciprocal, then negates. >>> f 3 -0.25 Let's explore some alternative ways to write this function. >>> let f1 x = negate . recip . succ $ x >>> let f2 x = negate . recip $ succ x >>> let f3 x = negate (recip (succ x)) Of those, I like reading @f3@ the best. But the parentheses add some visual noise and we still have to understand it from the inside out. Let's see how you might write this function with Overture. >>> let f4 x = negate <. recip <. succ <| x >>> let f5 x = negate <. recip <| succ x >>> let f6 = negate <. recip <. succ >>> let f7 = succ .> recip .> negate >>> let f8 x = succ x |> recip .> negate >>> let f9 x = x |> succ .> recip .> negate @f6@ is basically the same as the original @f@, but it hints at which way the data will be flowing through it. @f9@ is my favorite because I can easily see that I take some value and apply a series of transformations to it. If I wanted to express this function in the pointfree style, I would prefer @f7@ because it reads from left to right. -} module Overture where -- * Function composition {- | . This is like the '.' operator from the "Prelude". This function combines two other functions. The result of @'compose' f g@ is a new function that applies @f@ first and then applies @g@. In other words, @'compose' f g x@ is the same as @g (f x)@. >>> let f = compose succ recip >>> f 9 0.1 Composing many functions together quickly becomes unwieldy. Use '.>' or '<.' instead. >>> let g = succ `compose` recip `compose` negate >>> g 9 -0.1 -} compose :: (a -> b) -> (b -> c) -> (a -> c) compose f g = \ x -> g (f x) {- | Left-associative 'compose' operator. This is like a flipped version of the '.' operator from the "Prelude". It is also similar to the 'Control.Category.>>>' operator from "Control.Category". This operator combines two other functions more naturally than 'compose'. The result of @f '.>' g@ is a new function that applies @f@ first and then applies @g@. >>> let f = succ .> recip >>> f 9 0.1 When reading code, pronounce this operator as "and then". So the above example could be read as: "Add one, /and then/ take the reciprocal." Thanks to its high precedence, composing many functions together is easy with this operator. >>> let g = succ .> recip .> negate >>> g 9 -0.1 -} infixl 9 .> (.>) :: (a -> b) -> (b -> c) -> (a -> c) f .> g = compose f g {- | Right-associative 'compose' operator. This is like the '.' operator from the "Prelude". It is also similar to the 'Control.Category.<<<' operator from "Control.Category". Sometimes it is more convenient to combine functions from right to left. The result of @g '<.' f@ is a new function that applies @g@ but first applies @f@. >>> let f = recip <. succ >>> f 9 0.1 Pronounce this operator as "but first" when reading code. The example above could be read as: "Take the reciprocal, /but first/ add one." Composing many functions together is easy with this operator thanks to its high precedence. >>> let g = negate <. recip <. succ >>> g 9 -0.1 -} infixr 9 <. (<.) :: (b -> c) -> (a -> b) -> (a -> c) g <. f = compose f g -- * Function application {- | . This is like the '$' operator from the "Prelude". This function applies an argument to function. >>> apply 4 succ 5 Using this function to apply many arguments is cumbersome. Use '|>' or '<|' instead. >>> 4 `apply` succ `apply` recip 0.2 This function usually isn't necessary since @'apply' x f@ is the same as @f x@. However it can come in handy when working with higher-order functions. >>> map (apply 4) [succ, recip] [5.0,0.25] -} apply :: a -> (a -> b) -> b apply x f = f x {- | Left-associative 'apply' operator. This is like a flipped version of the '$' operator from the "Prelude". This operator applies an argument to a function. The result of @x '|>' f@ is @f x@. >>> 4 |> succ 5 Since this operator has such low precedence, it can be used to remove parentheses in complicated expressions. >>> 4 |> succ |> recip 0.2 When reading code, pronounce this operator as "pipe into". So the above example can be read as: "Four /piped into/ plus one, /piped into/ the reciprocal." It can also be used with higher-order functions, although 'apply' might be clearer. >>> map (4 |>) [succ, recip] [5.0,0.25] -} infixl 0 |> (|>) :: a -> (a -> b) -> b x |> f = apply x f {- | Right-associative 'apply' operator. This is like the '$' operator from the "Prelude". Sometimes it is more convenient to apply arguments right to left. The result of @f '<|' x@ is @f x@. >>> succ <| 4 5 Like '|>', this operator has low precedence so it can be used to remove parentheses. >>> recip <| succ <| 4 0.2 Pronounce this operator as "pipe from" when reading code. The example above can be read as: "The reciprocal /piped from/ plus one, /piped from/ five." This operator is a convenient alternative to @flip 'apply'@. >>> map (<| 4) [succ, recip] [5.0,0.25] -} infixr 0 <| (<|) :: (a -> b) -> a -> b f <| x = apply x f -- ** Strict function application {- | Strict function application. This is like the '$!' operator from the "Prelude". This is the strict version of 'apply'. It evaluates its argument with 'seq' before applying it to the given function. In other words, @'apply'' x f@ is the same as @x \`seq\` 'apply' x f@. >>> apply' undefined (const 0) *** Exception: Prelude.undefined -} apply' :: a -> (a -> b) -> b apply' x f = x `seq` apply x f {- | Left-associative 'apply'' operator. This is like a flipped version of the '$!' operator from the "Prelude". This is the strict version of the '|>' operator. >>> undefined !> const 0 *** Exception: Prelude.undefined -} infixl 0 !> (!>) :: a -> (a -> b) -> b x !> f = apply' x f {- | Right-associative 'apply'' operator. This is like the '$!' operator from the "Prelude". This is the strict version of the '>> const 0 b) -> a -> b f