flow 1.0.8 → 1.0.9
raw patch · 9 files changed
+374/−376 lines, 9 filesdep ~basedep ~doctestsetup-changedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, doctest
API changes (from Hackage documentation)
Files
- CHANGELOG.md +7/−7
- Flow.hs +229/−229
- FlowTest.hs +6/−6
- LICENSE.md +23/−23
- README.md +67/−67
- Setup.hs +4/−4
- flow.cabal +7/−7
- package.yaml +30/−30
- stack.yaml +1/−3
CHANGELOG.md view
@@ -1,7 +1,7 @@-# Change log--Flow uses [Semantic Versioning][].-The change log is available through the [releases on GitHub][].--[Semantic Versioning]: http://semver.org/spec/v2.0.0.html-[releases on GitHub]: https://github.com/tfausak/flow/releases+# Change log + +Flow uses [Semantic Versioning][]. +The change log is available through the [releases on GitHub][]. + +[Semantic Versioning]: http://semver.org/spec/v2.0.0.html +[releases on GitHub]: https://github.com/tfausak/flow/releases
Flow.hs view
@@ -1,229 +1,229 @@-{- |- 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)--{- $setup- >>> import Prelude- >>> let f = (+ 3)- >>> let g = (* 3)- >>> let h = (^ 3)--}--{- |- prop> (x |> f) == f x-- prop> (x |> f |> g) == g (f x)-- 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.&').--}-infixl 0 |>-(|>) :: a -> (a -> b) -> b-x |> f = apply x f--{- |- prop> (f <| x) == f x-- prop> (g <| f <| x) == g (f x)-- 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.$').--}-infixr 0 <|-(<|) :: (a -> b) -> a -> b-f <| x = apply x f--{- |- prop> apply x f == f x-- 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]--}-apply :: a -> (a -> b) -> b-apply x f = f x--{- |- prop> (f .> g) x == g (f x)-- prop> (f .> g .> h) x == h (g (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.>>>').--}-infixl 9 .>-(.>) :: (a -> b) -> (b -> c) -> (a -> c)-f .> g = compose f g--{- |- prop> (g <. f) x == g (f x)-- prop> (h <. g <. f) x == h (g (f x))-- 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..').--}-infixr 9 <.-(<.) :: (b -> c) -> (a -> b) -> (a -> c)-g <. f = compose f g--{- |- prop> compose f g x == g (f x)-- 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]--}-compose :: (a -> b) -> (b -> c) -> (a -> c)-compose f g = \ x -> g (f x)--{- |- prop> (x !> f) == seq x (f x)-- prop> (x !> f !> g) == let y = seq x (f x) in seq y (g y)-- Left-associative 'apply'' operator. Read as "strict apply forward" or- "strict pipe info". 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- ...--}-infixl 0 !>-(!>) :: a -> (a -> b) -> b-x !> f = apply' x f--{- |- prop> (f <! x) == seq x (f x)-- prop> (g <! f <! x) == let y = seq x (f x) in seq y (g y)-- 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- ...--}-infixr 0 <!-(<!) :: (a -> b) -> a -> b-f <! x = apply' x f--{- |- prop> apply' x f == seq x (f x)-- 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- ...--}-apply' :: a -> (a -> b) -> b-apply' x f = seq x (apply x f)+{- | + 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) + +{- $setup + >>> import Prelude + >>> let f = (+ 3) + >>> let g = (* 3) + >>> let h = (^ 3) +-} + +{- | + prop> (x |> f) == f x + + prop> (x |> f |> g) == g (f x) + + 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.&'). +-} +infixl 0 |> +(|>) :: a -> (a -> b) -> b +x |> f = apply x f + +{- | + prop> (f <| x) == f x + + prop> (g <| f <| x) == g (f x) + + 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.$'). +-} +infixr 0 <| +(<|) :: (a -> b) -> a -> b +f <| x = apply x f + +{- | + prop> apply x f == f x + + 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] +-} +apply :: a -> (a -> b) -> b +apply x f = f x + +{- | + prop> (f .> g) x == g (f x) + + prop> (f .> g .> h) x == h (g (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.>>>'). +-} +infixl 9 .> +(.>) :: (a -> b) -> (b -> c) -> (a -> c) +f .> g = compose f g + +{- | + prop> (g <. f) x == g (f x) + + prop> (h <. g <. f) x == h (g (f x)) + + 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..'). +-} +infixr 9 <. +(<.) :: (b -> c) -> (a -> b) -> (a -> c) +g <. f = compose f g + +{- | + prop> compose f g x == g (f x) + + 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] +-} +compose :: (a -> b) -> (b -> c) -> (a -> c) +compose f g = \ x -> g (f x) + +{- | + prop> (x !> f) == seq x (f x) + + prop> (x !> f !> g) == let y = seq x (f x) in seq y (g y) + + Left-associative 'apply'' operator. Read as "strict apply forward" or + "strict pipe info". 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 + ... +-} +infixl 0 !> +(!>) :: a -> (a -> b) -> b +x !> f = apply' x f + +{- | + prop> (f <! x) == seq x (f x) + + prop> (g <! f <! x) == let y = seq x (f x) in seq y (g y) + + 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 + ... +-} +infixr 0 <! +(<!) :: (a -> b) -> a -> b +f <! x = apply' x f + +{- | + prop> apply' x f == seq x (f x) + + 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 + ... +-} +apply' :: a -> (a -> b) -> b +apply' x f = seq x (apply x f)
FlowTest.hs view
@@ -1,6 +1,6 @@-module Main (main) where--import Test.DocTest (doctest)--main :: IO ()-main = doctest ["Flow.hs"]+module Main (main) where + +import Test.DocTest (doctest) + +main :: IO () +main = doctest ["Flow.hs"]
LICENSE.md view
@@ -1,23 +1,23 @@-[The MIT License (MIT)][]--Copyright (c) 2016 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.--[The MIT License (MIT)]: https://opensource.org/licenses/MIT+[The MIT License (MIT)][] + +Copyright (c) 2016 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. + +[The MIT License (MIT)]: https://opensource.org/licenses/MIT
README.md view
@@ -1,67 +1,67 @@-# [Flow][]--Write more understandable Haskell.--[![Version badge][]][version]-[![Build badge][]][build]--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.*-```--See [the change log][] for a detailed list of changes.--## 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 |> f</code> | `x & f`-<code>f <| 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)`--For more information about Flow, please read [the Haddock documentation][].--[Flow]: http://taylor.fausak.me/flow/-[Version badge]: https://www.stackage.org/package/flow/badge/nightly?label=version-[version]: https://www.stackage.org/package/flow-[Build badge]: https://travis-ci.org/tfausak/flow.svg?branch=master-[build]: https://travis-ci.org/tfausak/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 change log]: CHANGELOG.md-[the base package]: http://hackage.haskell.org/package/base-[the haddock documentation]: https://hackage.haskell.org/package/flow/docs/Flow.html+# [Flow][] + +Write more understandable Haskell. + +[![Version badge][]][version] +[![Build badge][]][build] + +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.* +``` + +See [the change log][] for a detailed list of changes. + +## 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 |> f</code> | `x & f` +<code>f <| 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)` + +For more information about Flow, please read [the Haddock documentation][]. + +[Flow]: http://taylor.fausak.me/flow/ +[Version badge]: https://www.stackage.org/package/flow/badge/nightly?label=version +[version]: https://www.stackage.org/package/flow +[Build badge]: https://travis-ci.org/tfausak/flow.svg?branch=master +[build]: https://travis-ci.org/tfausak/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 change log]: CHANGELOG.md +[the base package]: http://hackage.haskell.org/package/base +[the haddock documentation]: https://hackage.haskell.org/package/flow/docs/Flow.html
Setup.hs view
@@ -1,4 +1,4 @@-import qualified Distribution.Simple--main :: IO ()-main = Distribution.Simple.defaultMain+import qualified Distribution.Simple + +main :: IO () +main = Distribution.Simple.defaultMain
flow.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: flow-version: 1.0.8+version: 1.0.9 synopsis: Write more understandable Haskell. description: Flow provides operators for writing more understandable Haskell. category: Combinators, Functions, Utility@@ -28,21 +28,21 @@ library ghc-options: -Wall build-depends:- base <5+ base < 5 exposed-modules: Flow other-modules: Paths_flow default-language: Haskell2010 -test-suite flow-test-suite+test-suite test type: exitcode-stdio-1.0 main-is: FlowTest.hs ghc-options: -Wall build-depends:- base- , doctest >=0.9 && <0.13+ base < 5+ , doctest >= 0.9 && < 0.14 , flow- , QuickCheck ==2.*- , template-haskell ==2.*+ , QuickCheck == 2.*+ , template-haskell == 2.* default-language: Haskell2010
package.yaml view
@@ -1,30 +1,30 @@-category: Combinators, Functions, Utility-description: Flow provides operators for writing more understandable Haskell.-extra-source-files:-- CHANGELOG.md-- LICENSE.md-- package.yaml-- README.md-- stack.yaml-ghc-options:-- -Wall-github: tfausak/flow-library:- dependencies:- - base <5- exposed-modules:- - Flow-license: MIT-maintainer: Taylor Fausak-name: flow-synopsis: Write more understandable Haskell.-tests:- flow-test-suite:- dependencies:- - base- - doctest >=0.9 && <0.13- - flow- - QuickCheck ==2.*- - template-haskell ==2.*- main: FlowTest.hs-version: '1.0.8'+name: flow +version: 1.0.9 + +category: Combinators, Functions, Utility +description: Flow provides operators for writing more understandable Haskell. +extra-source-files: + - CHANGELOG.md + - LICENSE.md + - package.yaml + - README.md + - stack.yaml +github: tfausak/flow +license: MIT +maintainer: Taylor Fausak +synopsis: Write more understandable Haskell. + +dependencies: base < 5 +ghc-options: -Wall + +library: + exposed-modules: Flow + +tests: + test: + dependencies: + - doctest >= 0.9 && < 0.14 + - flow + - QuickCheck == 2.* + - template-haskell == 2.* + main: FlowTest.hs
stack.yaml view
@@ -1,3 +1,1 @@-install-ghc: true-require-stack-version: ! '>=1.0.4'-resolver: nightly-2016-05-26+resolver: lts-9.0