diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,4 @@
+# Change log
+
+Flow follows the [Package Versioning Policy](https://pvp.haskell.org).
+You can find release notes [on GitHub](https://github.com/tfausak/flow/releases).
diff --git a/LICENSE.markdown b/LICENSE.markdown
deleted file mode 100644
--- a/LICENSE.markdown
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2021 Taylor Fausak
-
-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.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Taylor Fausak
+
+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.
diff --git a/README.markdown b/README.markdown
deleted file mode 100644
--- a/README.markdown
+++ /dev/null
@@ -1,80 +0,0 @@
-# [Flow][]
-
-[![CI](https://github.com/tfausak/flow/workflows/CI/badge.svg)](https://github.com/tfausak/flow/actions/new)
-[![Hackage](https://img.shields.io/hackage/v/flow)](https://hackage.haskell.org/package/flow)
-[![Stackage](https://www.stackage.org/package/flow/badge/nightly?label=stackage)](https://www.stackage.org/package/flow)
-
-Write more understandable Haskell.
-
-Flow is a package that provides functions and operators for writing more
-understandable Haskell. It is an alternative to some common idioms like
-[`($)`][] for function application and [`(.)`][] for function composition.
-
--   [Requirements](#requirements)
--   [Installation](#installation)
--   [Usage](#usage)
-    -   [Cheat sheet](#cheat-sheet)
-
-## Requirements
-
-Flow requires a Haskell compiler. It is tested with recent versions of GHC, but
-older or different compilers should be acceptable. For installation with Cabal,
-Flow requires at least Cabal 1.8.
-
-## Installation
-
-To add Flow as a dependency to your package, add it to your Cabal file.
-
-```
-build-depends: flow ==1.0.*
-```
-
-## Usage
-
-Flow is designed to be imported unqualified. It does not export anything that
-conflicts with [the base package][].
-
-``` hs
-import Flow
-```
-
-### Cheat sheet
-
-Flow            | Base
---------------- | -------------
-<code>x &#124;> f</code> | `x & f`
-<code>f <&#124; x</code> | `f $ x`
-`apply x f`     | `f x`
-`f .> g`        | `f >>> g`
-`g <. f`        | `g . f`
-`compose f g x` | `g (f x)`
-`x !> f`        | -
-`f <! x`        | `f $! x`
-`apply' x f`    | `seq x (f x)`
-
-### Converting existing code
-
-If you want to uniformly use flow operators you can use [HLint] with the
-`hlint-flow.yaml` file. For easy use, it is best to extract the
-`hlint-flow.yaml` to your project directory and do
-
-``` sh
-> hlint -h hlint-flow.yaml <source file>
-```
-
-or
-
-``` sh
-> hlint --git -h hlint-flow.yaml
-```
-
-to check all Haskell source tracked by git.
-
-For more information about Flow, please read [the Haddock documentation][].
-
-[HLint]: https://github.com/ndmitchell/hlint
-[Flow]: http://taylor.fausak.me/flow/
-[`($)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:-36-
-[`(.)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:.
-[the base package]: http://hackage.haskell.org/package/base
-[the haddock documentation]: https://hackage.haskell.org/package/flow/docs/Flow.html
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,79 @@
+# [Flow][]
+
+[![CI](https://github.com/tfausak/flow/actions/workflows/ci.yml/badge.svg)](https://github.com/tfausak/flow/actions/workflows/ci.yml)
+[![Hackage](https://badgen.net/hackage/v/flow)](https://hackage.haskell.org/package/flow)
+
+Write more understandable Haskell.
+
+Flow is a package that provides functions and operators for writing more
+understandable Haskell. It is an alternative to some common idioms like
+[`($)`][] for function application and [`(.)`][] for function composition.
+
+-   [Requirements](#requirements)
+-   [Installation](#installation)
+-   [Usage](#usage)
+    -   [Cheat sheet](#cheat-sheet)
+
+## Requirements
+
+Flow requires a Haskell compiler. It is tested with recent versions of GHC, but
+older or different compilers should be acceptable. For installation with Cabal,
+Flow requires at least Cabal 2.2.
+
+## Installation
+
+To add Flow as a dependency to your package, add it to your Cabal file.
+
+```
+build-depends: flow ==2.0.*
+```
+
+## Usage
+
+Flow is designed to be imported unqualified. It does not export anything that
+conflicts with [the base package][].
+
+``` hs
+import Flow
+```
+
+### Cheat sheet
+
+Flow            | Base
+--------------- | -------------
+<code>x &#124;> f</code> | `x & f`
+<code>f <&#124; x</code> | `f $ x`
+`apply x f`     | `f x`
+`f .> g`        | `f >>> g`
+`g <. f`        | `g . f`
+`compose f g x` | `g (f x)`
+`x !> f`        | -
+`f <! x`        | `f $! x`
+`apply' x f`    | `seq x (f x)`
+
+### Converting existing code
+
+If you want to uniformly use flow operators you can use [HLint] with the
+`hlint-flow.yaml` file. For easy use, it is best to extract the
+`hlint-flow.yaml` to your project directory and do
+
+``` sh
+> hlint -h hlint-flow.yaml <source file>
+```
+
+or
+
+``` sh
+> hlint --git -h hlint-flow.yaml
+```
+
+to check all Haskell source tracked by git.
+
+For more information about Flow, please read [the Haddock documentation][].
+
+[HLint]: https://github.com/ndmitchell/hlint
+[Flow]: http://taylor.fausak.me/flow/
+[`($)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:-36-
+[`(.)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:.
+[the base package]: http://hackage.haskell.org/package/base
+[the haddock documentation]: https://hackage.haskell.org/package/flow/docs/Flow.html
diff --git a/flow.cabal b/flow.cabal
--- a/flow.cabal
+++ b/flow.cabal
@@ -1,15 +1,15 @@
-cabal-version: >= 1.10
-
+cabal-version: 2.2
 name: flow
-version: 1.0.22
-
+version: 2.0.0.11
 synopsis: Write more understandable Haskell.
 description: Flow provides operators for writing more understandable Haskell.
-
 build-type: Simple
 category: Combinators, Functions, Utility
-extra-source-files: README.markdown
-license-file: LICENSE.markdown
+extra-doc-files:
+  CHANGELOG.md
+  README.md
+
+license-file: LICENSE.txt
 license: MIT
 maintainer: Taylor Fausak
 
@@ -17,27 +17,44 @@
   location: https://github.com/tfausak/flow
   type: git
 
-library
-  build-depends:
-    base >= 4.13.0 && < 4.16
+flag pedantic
+  default: False
+  description: Enables @-Werror@, which turns warnings into errors.
+  manual: True
+
+common library
+  build-depends: base ^>=4.20.0.0 || ^>=4.21.0.0 || ^>=4.22.0.0
   default-language: Haskell2010
-  exposed-modules: Flow
   ghc-options:
     -Weverything
+    -Wno-all-missed-specialisations
+    -Wno-implicit-prelude
     -Wno-missing-exported-signatures
+    -Wno-missing-safe-haskell-mode
+    -Wno-prepositive-qualified-module
     -Wno-safe
-  hs-source-dirs: src/lib
 
-  if impl(ghc >= 8.10)
-    ghc-options:
-      -Wno-missing-safe-haskell-mode
+  if flag(pedantic)
+    ghc-options: -Werror
 
-test-suite test
+common executable
+  import: library
+  build-depends: flow
+  ghc-options:
+    -rtsopts
+    -threaded
+
+library
+  import: library
+  -- cabal-gild: discover source/library
+  exposed-modules: Flow
+  hs-source-dirs: source/library
+
+test-suite flow-test-suite
+  import: executable
   build-depends:
-    base -any
-    , flow -any
-    , HUnit >= 1.6.1 && < 1.7
-  default-language: Haskell2010
-  hs-source-dirs: src/test
+    HUnit ^>=1.6.2.0
+
+  hs-source-dirs: source/test-suite
   main-is: Main.hs
   type: exitcode-stdio-1.0
diff --git a/source/library/Flow.hs b/source/library/Flow.hs
new file mode 100644
--- /dev/null
+++ b/source/library/Flow.hs
@@ -0,0 +1,273 @@
+-- | Flow provides operators for writing more understandable Haskell. It is an
+-- alternative to some common idioms like ('Prelude.$') for function
+-- application and ('Prelude..') for function composition.
+--
+-- Flow is designed to be imported unqualified. It does not export anything
+-- that conflicts with the base package.
+--
+-- >>> import Flow
+--
+-- == Rationale
+--
+-- I think that Haskell can be hard to read. It has two operators for applying
+-- functions. Both are not really necessary and only serve to reduce
+-- parentheses. But they make code hard to read. People who do not already
+-- know Haskell have no chance of guessing what @foo $ bar@ or @baz & qux@
+-- mean.
+--
+-- Those that do know Haskell are forced to read lines forwards and backwards
+-- at the same time, thanks to function composition. Even something simple,
+-- like finding the minimum element, bounces around: @f = head . sort@.
+--
+-- I think we can do better. By using directional operators, we can allow
+-- readers to move their eye in only one direction, be that left-to-right or
+-- right-to-left. And by using idioms common in other programming languages,
+-- we can allow people who aren't familiar with Haskell to guess at the
+-- meaning.
+--
+-- So instead of ('Prelude.$'), I propose ('<|'). It is a pipe, which anyone
+-- who has touched a Unix system should be familiar with. And it points in the
+-- direction it sends arguments along. Similarly, replace ('Data.Function.&')
+-- with ('|>'). And for composition, ('<.') replaces ('Prelude..'). I would
+-- have preferred @<<@, but its counterpart @>>@ is taken by Haskell's syntax.
+-- So-called "backwards" composition is normally expressed with
+-- ('Control.Category.>>>'), which Flow provides as ('.>').
+module Flow
+  ( -- * Function application
+    (|>),
+    (<|),
+    apply,
+
+    -- * Function composition
+    (.>),
+    (<.),
+    compose,
+
+    -- * Strict function application
+    (!>),
+    (<!),
+    apply',
+  )
+where
+
+import qualified Prelude
+
+-- | Left-associative 'apply' operator. Read as "apply forward" or "pipe into".
+-- Use this to create long chains of computation that suggest which direction
+-- things move in.
+--
+-- >>> 3 |> succ |> recip |> negate
+-- -0.25
+--
+-- Or use it anywhere you would use ('Data.Function.&').
+--
+-- prop> \ x -> (x |> f) == f x
+--
+-- prop> \ x -> (x |> f |> g) == g (f x)
+infixl 0 |>
+
+{-# INLINE (|>) #-}
+(|>) :: a -> (a -> b) -> b
+(|>) = apply
+
+-- | Right-associative 'apply' operator. Read as "apply backward" or "pipe
+-- from". Use this to create long chains of computation that suggest which
+-- direction things move in. You may prefer this operator over ('|>') for
+-- 'Prelude.IO' actions since it puts the last function first.
+--
+-- >>> print <| negate <| recip <| succ <| 3
+-- -0.25
+--
+-- Or use it anywhere you would use ('Prelude.$').
+--
+-- Note that ('<|') and ('|>') have the same precedence, so they cannot be used
+-- together.
+--
+-- >>> -- This doesn't work!
+-- >>> -- print <| 3 |> succ |> recip |> negate
+--
+-- prop> \ x -> (f <| x) == f x
+--
+-- prop> \ x -> (g <| f <| x) == g (f x)
+infixr 0 <|
+
+{-# INLINE (<|) #-}
+(<|) :: (a -> b) -> a -> b
+(<|) f = f
+
+-- | Function application. This function usually isn't necessary, but it can be
+-- more readable than some alternatives when used with higher-order functions
+-- like 'Prelude.map'.
+--
+-- >>> map (apply 2) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+--
+-- In general you should prefer using an explicit lambda or operator section.
+--
+-- >>> map (\ f -> 2 |> f) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+-- >>> map (2 |>) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+-- >>> map (<| 2) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+--
+-- prop> \ x -> apply x f == f x
+{-# INLINE apply #-}
+apply :: a -> (a -> b) -> b
+apply x f = f x
+
+-- | Left-associative 'compose' operator. Read as "compose forward" or "and
+-- then". Use this to create long chains of computation that suggest which
+-- direction things move in.
+--
+-- >>> let f = succ .> recip .> negate
+-- >>> f 3
+-- -0.25
+--
+-- Or use it anywhere you would use ('Control.Category.>>>').
+--
+-- prop> \ x -> (f .> g) x == g (f x)
+--
+-- prop> \ x -> (f .> g .> h) x == h (g (f x))
+infixl 9 .>
+
+{-# INLINE (.>) #-}
+(.>) :: (a -> b) -> (b -> c) -> (a -> c)
+f .> g = compose f g
+
+-- | Right-associative 'compose' operator. Read as "compose backward" or "but
+-- first". Use this to create long chains of computation that suggest which
+-- direction things move in. You may prefer this operator over ('.>') for
+-- 'Prelude.IO' actions since it puts the last function first.
+--
+-- >>> let f = print <. negate <. recip <. succ
+-- >>> f 3
+-- -0.25
+--
+-- Or use it anywhere you would use ('Prelude..').
+--
+-- Note that ('<.') and ('.>') have the same precedence, so they cannot be used
+-- together.
+--
+-- >>> -- This doesn't work!
+-- >>> -- print <. succ .> recip .> negate
+--
+-- prop> \ x -> (g <. f) x == g (f x)
+--
+-- prop> \ x -> (h <. g <. f) x == h (g (f x))
+infixr 9 <.
+
+{-# INLINE (<.) #-}
+(<.) :: (b -> c) -> (a -> b) -> (a -> c)
+g <. f = compose f g
+
+-- | Function composition. This function usually isn't necessary, but it can be
+-- more readable than some alternatives when used with higher-order functions
+-- like 'Prelude.map'.
+--
+-- >>> let fs = map (compose succ) [recip, negate]
+-- >>> map (apply 3) fs
+-- [0.25,-4.0]
+--
+-- In general you should prefer using an explicit lambda or operator section.
+--
+-- >>> map (\ f -> f 3) (map (\ f -> succ .> f) [recip, negate])
+-- [0.25,-4.0]
+-- >>> map (\ f -> f 3) (map (succ .>) [recip, negate])
+-- [0.25,-4.0]
+-- >>> map (\ f -> f 3) (map (<. succ) [recip, negate])
+-- [0.25,-4.0]
+--
+-- prop> \ x -> compose f g x == g (f x)
+{-# INLINE compose #-}
+compose :: (a -> b) -> (b -> c) -> (a -> c)
+compose f g = \x -> g (f x)
+
+-- | Left-associative 'apply'' operator. Read as "strict apply forward" or
+-- "strict pipe into". Use this to create long chains of computation that
+-- suggest which direction things move in.
+--
+-- >>> 3 !> succ !> recip !> negate
+-- -0.25
+--
+-- The difference between this and ('|>') is that this evaluates its argument
+-- before passing it to the function.
+--
+-- >>> undefined |> const True
+-- True
+-- >>> undefined !> const True
+-- *** Exception: Prelude.undefined
+-- ...
+--
+-- prop> \ x -> (x !> f) == seq x (f x)
+--
+-- prop> \ x -> (x !> f !> g) == let y = seq x (f x) in seq y (g y)
+infixl 0 !>
+
+{-# INLINE (!>) #-}
+(!>) :: a -> (a -> b) -> b
+(!>) = \x f -> f <! x
+
+-- | Right-associative 'apply'' operator. Read as "strict apply backward" or
+-- "strict pipe from". Use this to create long chains of computation that
+-- suggest which direction things move in. You may prefer this operator over
+-- ('!>') for 'Prelude.IO' actions since it puts the last function first.
+--
+-- >>> print <! negate <! recip <! succ <! 3
+-- -0.25
+--
+-- Or use it anywhere you would use ('Prelude.$!').
+--
+-- The difference between this and ('<|') is that this evaluates its argument
+-- before passing it to the function.
+--
+-- >>> const True <| undefined
+-- True
+-- >>> const True <! undefined
+-- *** Exception: Prelude.undefined
+-- ...
+--
+-- Note that ('<!') and ('!>') have the same precedence, so they cannot be used
+-- together.
+--
+-- >>> -- This doesn't work!
+-- >>> -- print <! 3 !> succ !> recip !> negate
+--
+-- prop> \ x -> (f <! x) == seq x (f x)
+--
+-- prop> \ x -> (g <! f <! x) == let y = seq x (f x) in seq y (g y)
+infixr 0 <!
+
+{-# INLINE (<!) #-}
+(<!) :: (a -> b) -> a -> b
+(<!) = (Prelude.$!)
+
+-- | Strict function application. This function usually isn't necessary, but it
+-- can be more readable than some alternatives when used with higher-order
+-- functions like 'Prelude.map'.
+--
+-- >>> map (apply' 2) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+--
+-- The different between this and 'apply' is that this evaluates its argument
+-- before passing it to the function.
+--
+-- >>> apply undefined (const True)
+-- True
+-- >>> apply' undefined (const True)
+-- *** Exception: Prelude.undefined
+-- ...
+--
+-- In general you should prefer using an explicit lambda or operator section.
+--
+-- >>> map (\ f -> 2 !> f) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+-- >>> map (2 !>) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+-- >>> map (<! 2) [succ, recip, negate]
+-- [3.0,0.5,-2.0]
+--
+-- prop> \ x -> apply' x f == seq x (f x)
+{-# INLINE apply' #-}
+apply' :: a -> (a -> b) -> b
+apply' = (!>)
diff --git a/source/test-suite/Main.hs b/source/test-suite/Main.hs
new file mode 100644
--- /dev/null
+++ b/source/test-suite/Main.hs
@@ -0,0 +1,42 @@
+import qualified Control.Monad as Monad
+import qualified Flow
+import qualified System.Exit as Exit
+import qualified Test.HUnit as Test
+
+main :: IO ()
+main = do
+  counts <-
+    Test.runTestTT $
+      Test.TestList
+        [ True Test.~?= True,
+          (3 Flow.|> succ Flow.|> recip Flow.|> negate) Test.~?= (-0.25 :: Double),
+          (negate Flow.<| recip Flow.<| succ Flow.<| 3) Test.~?= (-0.25 :: Double),
+          fmap (Flow.apply 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],
+          fmap (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],
+          fmap (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],
+          fmap (Flow.<| 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],
+          fmap (Flow.apply 3 . Flow.compose succ) [recip, negate]
+            Test.~?= [0.25, -4 :: Double],
+          (succ Flow..> recip Flow..> negate) 3 Test.~?= (-0.25 :: Double),
+          (negate Flow.<. recip Flow.<. succ) 3 Test.~?= (-0.25 :: Double),
+          fmap ((\f -> f 3) . (succ Flow..>)) [recip, negate]
+            Test.~?= [0.25, -4 :: Double],
+          fmap ((\f -> f 3) . (succ Flow..>)) [recip, negate]
+            Test.~?= [0.25, -4 :: Double],
+          fmap ((\f -> f 3) . (Flow.<. succ)) [recip, negate]
+            Test.~?= [0.25, -4 :: Double],
+          (3 Flow.!> succ Flow.!> recip Flow.!> negate) Test.~?= (-0.25 :: Double),
+          (undefined Flow.|> const True) Test.~?= True,
+          (negate Flow.<! recip Flow.<! succ Flow.<! 3) Test.~?= (-0.25 :: Double),
+          (const True Flow.<| undefined) Test.~?= True,
+          fmap (Flow.apply' 2) [succ, recip, negate]
+            Test.~?= [3, 0.5, -2 :: Double],
+          Flow.apply undefined (const True) Test.~?= True,
+          fmap (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],
+          fmap (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],
+          fmap (Flow.<! 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
+        ]
+
+  let hasErrors = Test.errors counts /= 0
+      hasFailures = Test.failures counts /= 0
+  Monad.when (hasErrors || hasFailures) Exit.exitFailure
diff --git a/src/lib/Flow.hs b/src/lib/Flow.hs
deleted file mode 100644
--- a/src/lib/Flow.hs
+++ /dev/null
@@ -1,247 +0,0 @@
--- | Flow provides operators for writing more understandable Haskell. It is an
--- alternative to some common idioms like ('Prelude.$') for function
--- application and ('Prelude..') for function composition.
---
--- Flow is designed to be imported unqualified. It does not export anything
--- that conflicts with the base package.
---
--- >>> import Flow
---
--- == Rationale
---
--- I think that Haskell can be hard to read. It has two operators for applying
--- functions. Both are not really necessary and only serve to reduce
--- parentheses. But they make code hard to read. People who do not already
--- know Haskell have no chance of guessing what @foo $ bar@ or @baz & qux@
--- mean.
---
--- Those that do know Haskell are forced to read lines forwards and backwards
--- at the same time, thanks to function composition. Even something simple,
--- like finding the minimum element, bounces around: @f = head . sort@.
---
--- I think we can do better. By using directional operators, we can allow
--- readers to move their eye in only one direction, be that left-to-right or
--- right-to-left. And by using idioms common in other programming languages,
--- we can allow people who aren't familiar with Haskell to guess at the
--- meaning.
---
--- So instead of ('Prelude.$'), I propose ('<|'). It is a pipe, which anyone
--- who has touched a Unix system should be familiar with. And it points in the
--- direction it sends arguments along. Similarly, replace ('Prelude.&') with
--- ('|>'). And for composition, ('<.') replaces ('Prelude..'). I would have
--- preferred @<<@, but its counterpart @>>@ is taken by Haskell's syntax.
--- So-called "backwards" composition is normally expressed with
--- ('Control.Category.>>>'), which Flow provides as ('.>').
-module Flow (
-    -- * Function application
-    (|>), (<|), apply,
-    -- * Function composition
-    (.>), (<.), compose,
-    -- * Strict function application
-    (!>), (<!), apply',
-) where
-
-import Prelude (seq)
-
--- | Left-associative 'apply' operator. Read as "apply forward" or "pipe into".
--- Use this to create long chains of computation that suggest which direction
--- things move in.
---
--- >>> 3 |> succ |> recip |> negate
--- -0.25
---
--- Or use it anywhere you would use ('Prelude.&').
---
--- prop> \ x -> (x |> f) == f x
---
--- prop> \ x -> (x |> f |> g) == g (f x)
-infixl 0 |>
-(|>) :: a -> (a -> b) -> b
-x |> f = apply x f
-
--- | Right-associative 'apply' operator. Read as "apply backward" or "pipe
--- from". Use this to create long chains of computation that suggest which
--- direction things move in. You may prefer this operator over ('|>') for
--- 'Prelude.IO' actions since it puts the last function first.
---
--- >>> print <| negate <| recip <| succ <| 3
--- -0.25
---
--- Or use it anywhere you would use ('Prelude.$').
---
--- Note that ('<|') and ('|>') have the same precedence, so they cannot be used
--- together.
---
--- >>> -- This doesn't work!
--- >>> -- print <| 3 |> succ |> recip |> negate
---
--- prop> \ x -> (f <| x) == f x
---
--- prop> \ x -> (g <| f <| x) == g (f x)
-infixr 0 <|
-(<|) :: (a -> b) -> a -> b
-f <| x = apply x f
-
--- | Function application. This function usually isn't necessary, but it can be
--- more readable than some alternatives when used with higher-order functions
--- like 'Prelude.map'.
---
--- >>> map (apply 2) [succ, recip, negate]
--- [3.0,0.5,-2.0]
---
--- In general you should prefer using an explicit lambda or operator section.
---
--- >>> map (\ f -> 2 |> f) [succ, recip, negate]
--- [3.0,0.5,-2.0]
--- >>> map (2 |>) [succ, recip, negate]
--- [3.0,0.5,-2.0]
--- >>> map (<| 2) [succ, recip, negate]
--- [3.0,0.5,-2.0]
---
--- prop> \ x -> apply x f == f x
-apply :: a -> (a -> b) -> b
-apply x f = f x
-
--- | Left-associative 'compose' operator. Read as "compose forward" or "and
--- then". Use this to create long chains of computation that suggest which
--- direction things move in.
---
--- >>> let f = succ .> recip .> negate
--- >>> f 3
--- -0.25
---
--- Or use it anywhere you would use ('Control.Category.>>>').
---
--- prop> \ x -> (f .> g) x == g (f x)
---
--- prop> \ x -> (f .> g .> h) x == h (g (f x))
-infixl 9 .>
-(.>) :: (a -> b) -> (b -> c) -> (a -> c)
-f .> g = compose f g
-
--- | Right-associative 'compose' operator. Read as "compose backward" or "but
--- first". Use this to create long chains of computation that suggest which
--- direction things move in. You may prefer this operator over ('.>') for
--- 'Prelude.IO' actions since it puts the last function first.
---
--- >>> let f = print <. negate <. recip <. succ
--- >>> f 3
--- -0.25
---
--- Or use it anywhere you would use ('Prelude..').
---
--- Note that ('<.') and ('.>') have the same precedence, so they cannot be used
--- together.
---
--- >>> -- This doesn't work!
--- >>> -- print <. succ .> recip .> negate
---
--- prop> \ x -> (g <. f) x == g (f x)
---
--- prop> \ x -> (h <. g <. f) x == h (g (f x))
-infixr 9 <.
-(<.) :: (b -> c) -> (a -> b) -> (a -> c)
-g <. f = compose f g
-
--- | Function composition. This function usually isn't necessary, but it can be
--- more readable than some alternatives when used with higher-order functions
--- like 'Prelude.map'.
---
--- >>> let fs = map (compose succ) [recip, negate]
--- >>> map (apply 3) fs
--- [0.25,-4.0]
---
--- In general you should prefer using an explicit lambda or operator section.
---
--- >>> map (\ f -> f 3) (map (\ f -> succ .> f) [recip, negate])
--- [0.25,-4.0]
--- >>> map (\ f -> f 3) (map (succ .>) [recip, negate])
--- [0.25,-4.0]
--- >>> map (\ f -> f 3) (map (<. succ) [recip, negate])
--- [0.25,-4.0]
---
--- prop> \ x -> compose f g x == g (f x)
-compose :: (a -> b) -> (b -> c) -> (a -> c)
-compose f g = \ x -> g (f x)
-
--- | Left-associative 'apply'' operator. Read as "strict apply forward" or
--- "strict pipe into". Use this to create long chains of computation that
--- suggest which direction things move in.
---
--- >>> 3 !> succ !> recip !> negate
--- -0.25
---
--- The difference between this and ('|>') is that this evaluates its argument
--- before passing it to the function.
---
--- >>> undefined |> const True
--- True
--- >>> undefined !> const True
--- *** Exception: Prelude.undefined
--- ...
---
--- prop> \ x -> (x !> f) == seq x (f x)
---
--- prop> \ x -> (x !> f !> g) == let y = seq x (f x) in seq y (g y)
-infixl 0 !>
-(!>) :: a -> (a -> b) -> b
-x !> f = apply' x f
-
--- | Right-associative 'apply'' operator. Read as "strict apply backward" or
--- "strict pipe from". Use this to create long chains of computation that
--- suggest which direction things move in. You may prefer this operator over
--- ('!>') for 'Prelude.IO' actions since it puts the last function first.
---
--- >>> print <! negate <! recip <! succ <! 3
--- -0.25
---
--- The difference between this and ('<|') is that this evaluates its argument
--- before passing it to the function.
---
--- >>> const True <| undefined
--- True
--- >>> const True <! undefined
--- *** Exception: Prelude.undefined
--- ...
---
--- Note that ('<!') and ('!>') have the same precedence, so they cannot be used
--- together.
---
--- >>> -- This doesn't work!
--- >>> -- print <! 3 !> succ !> recip !> negate
---
--- prop> \ x -> (f <! x) == seq x (f x)
---
--- prop> \ x -> (g <! f <! x) == let y = seq x (f x) in seq y (g y)
-infixr 0 <!
-(<!) :: (a -> b) -> a -> b
-f <! x = apply' x f
-
--- | Strict function application. This function usually isn't necessary, but it
--- can be more readable than some alternatives when used with higher-order
--- functions like 'Prelude.map'.
---
--- >>> map (apply' 2) [succ, recip, negate]
--- [3.0,0.5,-2.0]
---
--- The different between this and 'apply' is that this evaluates its argument
--- before passing it to the function.
---
--- >>> apply undefined (const True)
--- True
--- >>> apply' undefined (const True)
--- *** Exception: Prelude.undefined
--- ...
---
--- In general you should prefer using an explicit lambda or operator section.
---
--- >>> map (\ f -> 2 !> f) [succ, recip, negate]
--- [3.0,0.5,-2.0]
--- >>> map (2 !>) [succ, recip, negate]
--- [3.0,0.5,-2.0]
--- >>> map (<! 2) [succ, recip, negate]
--- [3.0,0.5,-2.0]
---
--- prop> \ x -> apply' x f == seq x (f x)
-apply' :: a -> (a -> b) -> b
-apply' x f = seq x (apply x f)
diff --git a/src/test/Main.hs b/src/test/Main.hs
deleted file mode 100644
--- a/src/test/Main.hs
+++ /dev/null
@@ -1,36 +0,0 @@
-import qualified Control.Monad as Monad
-import qualified Flow
-import qualified System.Exit as Exit
-import qualified Test.HUnit as Test
-
-main :: IO ()
-main = do
-  counts <- Test.runTestTT $ Test.TestList
-    [ True Test.~?= True
-    , (3 Flow.|> succ Flow.|> recip Flow.|> negate) Test.~?= (-0.25 :: Double)
-    , (negate Flow.<| recip Flow.<| succ Flow.<| 3) Test.~?= (-0.25 :: Double)
-    , map (Flow.apply 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
-    , map (\ f -> 2 Flow.|> f) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
-    , map (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
-    , map (Flow.<| 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
-    , map (Flow.apply 3) (map (Flow.compose succ) [recip, negate]) Test.~?= [0.25, -4 :: Double]
-    , (succ Flow..> recip Flow..> negate) 3 Test.~?= (-0.25 :: Double)
-    , (negate Flow.<. recip Flow.<. succ) 3 Test.~?= (-0.25 :: Double)
-    , map (\ f -> f 3) (map (\ f -> succ Flow..> f) [recip, negate]) Test.~?= [0.25, -4 :: Double]
-    , map (\ f -> f 3) (map (succ Flow..>) [recip, negate]) Test.~?= [0.25, -4 :: Double]
-    , map (\ f -> f 3) (map (Flow.<. succ) [recip, negate]) Test.~?= [0.25, -4 :: Double]
-    , (3 Flow.!> succ Flow.!> recip Flow.!> negate) Test.~?= (-0.25 :: Double)
-    , (undefined Flow.|> const True) Test.~?= True
-    , (negate Flow.<! recip Flow.<! succ Flow.<! 3) Test.~?= (-0.25 :: Double)
-    , (const True Flow.<| undefined) Test.~?= True
-    , map (Flow.apply' 2) [succ, recip, negate]  Test.~?= [3, 0.5, -2 :: Double]
-    , Flow.apply undefined (const True) Test.~?= True
-    , map (\ f -> 2 Flow.!> f) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
-    , map (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
-    , map (Flow.<! 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]
-    ]
-
-  let
-    hasErrors = Test.errors counts /= 0
-    hasFailures = Test.failures counts /= 0
-  Monad.when (hasErrors || hasFailures) Exit.exitFailure
