flow-er (empty) → 1.0.0
raw patch · 17 files changed
+856/−0 lines, 17 filesdep +QuickCheckdep +basedep +doctestsetup-changed
Dependencies added: QuickCheck, base, doctest, flow, flow-er
Files
- LICENSE +21/−0
- README.md +3/−0
- Setup.hs +2/−0
- flow-er.cabal +75/−0
- src/Control/Flower.hs +69/−0
- src/Control/Flower/Applicative.hs +7/−0
- src/Control/Flower/Applicative/Lazy.hs +113/−0
- src/Control/Flower/Applicative/Strict.hs +83/−0
- src/Control/Flower/Apply.hs +7/−0
- src/Control/Flower/Apply/Lazy.hs +101/−0
- src/Control/Flower/Apply/Strict.hs +102/−0
- src/Control/Flower/Compose.hs +48/−0
- src/Control/Flower/Functor.hs +7/−0
- src/Control/Flower/Functor/Lazy.hs +78/−0
- src/Control/Flower/Functor/Strict.hs +58/−0
- src/Control/Flower/Monad.hs +63/−0
- test/doctests.hs +19/−0
+ LICENSE view
@@ -0,0 +1,21 @@+The MIT License (MIT)++Copyright (c) 2016 Brooklyn Zelenka++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.
+ README.md view
@@ -0,0 +1,3 @@+# :sweat_drops: flower+## \ˈflō'ər\+More [Flow](https://hackage.haskell.org/package/flow)
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ flow-er.cabal view
@@ -0,0 +1,75 @@+name: flow-er+version: 1.0.0+synopsis: Initial project template from stack+description: Please see README.md+homepage: https://github.com/expede/flower#README++license: MIT+license-file: LICENSE++author: Brooklyn Zelenka+maintainer: bez@brooklynzelenka.com++category: Combinators, Functions, Utility+build-type: Simple++extra-source-files: README.md+cabal-version: >= 1.24++library+ hs-source-dirs: src+ exposed-modules: Control.Flower++ , Control.Flower.Apply+ , Control.Flower.Apply.Lazy+ , Control.Flower.Apply.Strict++ , Control.Flower.Compose++ , Control.Flower.Functor+ , Control.Flower.Functor.Lazy+ , Control.Flower.Functor.Strict++ , Control.Flower.Applicative+ , Control.Flower.Applicative.Lazy+ , Control.Flower.Applicative.Strict++ , Control.Flower.Monad++ build-depends: base == 4.*+ , flow ==1.0.*+ hs-source-dirs: src+ ghc-options: -Wall -fno-warn-orphans+ default-language: Haskell2010++-- test-suite flower-test+-- type: exitcode-stdio-1.0+-- hs-source-dirs: test+-- main-is: Spec.hs+-- ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+-- default-language: Haskell2010+-- build-depends: base+-- , flow ==1.0.*+-- , flower+-- , tasty >= 0.10 && < 1.0+-- , tasty-hunit >= 0.9 && < 1.0+-- , tasty-smallcheck >= 0.8 && < 1.0+-- , tasty-quickcheck >= 0.8 && < 1.0+-- , smallcheck >= 1.1 && < 2.0+-- , checkers >= 0.4 && < 1.0++test-suite doctests+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ ghc-options: -Wall +RTS -N -RTS -threaded+ hs-source-dirs: test+ main-is: doctests.hs+ build-depends: base+ , QuickCheck ==2.8.*+ , doctest >= 0.9 && < 1.0+ , flow ==1.0.*+ , flow-er++source-repository head+ type: git+ location: https://github.com/expede/flower.git
+ src/Control/Flower.hs view
@@ -0,0 +1,69 @@+{-|+Module : Control.Flower+Description : Modern, readable, directional Haskell++== Use++>>> import Control.Flower++== Rationale++> Mathematics, rightly viewed, possesses not only truth,+> but supreme beauty -- a beauty cold and austere, like that of sculpture,+> without appeal to any part of our weaker nature, without the gorgeous+> trappings of painting or music, yet sublimely pure, and capable of a stern+> perfection such as only the greatest art can show. The true spirit of delight,+> the exaltation, the sense of being more than Man, which is the touchstone of+> the highest excellence, is to be found in mathematics as surely as poetry.+> - Bertrand Russell, "The Study of Mathematics"++Inspired by the wonderful @Flow@ package, Flower provides directional operators+for many common Haskell functions.++With the pipe operator ('|>') proliferating through OCaml, F#, and Elixir,+it's becoming clear which way the wind is blowing. A dataflow model is very+natural to functional programming _____.++Thinking in Haskell is multidimensional, reading forwards and backwards,+and through levels of abstraction. This is extremely powerful, but does introduce+a leaning curve (in grade school, when starting with Haskell, or both).++Here, instead of 'Prelude.$', we use '<|', or reversed with '|>'. Instead of+'Prelude.<$>', we use '<$', and reversed '$>'. Many of the combinators are+built up from meaningful character combinations. One such example is 'Prelude.lift2',+which is translated into '<$**'. '<$**', as 'f <$ a <* b <* c'.++Please do note that 'Control.Flower' exposes conflicting combinators versus the+standard 'Prelude'.++=== Teaching+Teaching concepts becomes simplified by providing a visual aid. Many of the operators+are made up of simpler symbols, much in the same way as the @Lens@ library.++One common challenge when teaching Haskell is showing what an applicative+or monad "mean". By using a progressive, modular picture of each abstraction,+we help build the intuition.++=== Reading+A focus on a single direction of data flow makes code easy to follow.++=== Simplify+All `lift`s (`fmap`, `liftA*` and `liftM*`) are unified as `lift*`.++-}+module Control.Flower (+ -- * Basic data flow+ module Control.Flower.Apply,+ module Control.Flower.Compose,++ -- * Functors+ module Control.Flower.Functor,+ module Control.Flower.Applicative,+ module Control.Flower.Monad+) where++import Control.Flower.Apply+import Control.Flower.Compose+import Control.Flower.Functor+import Control.Flower.Applicative+import Control.Flower.Monad
+ src/Control/Flower/Applicative.hs view
@@ -0,0 +1,7 @@+module Control.Flower.Applicative (+ module Control.Flower.Applicative.Lazy,+ module Control.Flower.Applicative.Strict+) where++import Control.Flower.Applicative.Lazy+import Control.Flower.Applicative.Strict
+ src/Control/Flower/Applicative/Lazy.hs view
@@ -0,0 +1,113 @@+{-|+Module : Control.Flower.Applicative.Lazy+Description : Combinators for directional lazy applicative functors+-}++module Control.Flower.Applicative.Lazy (+ ap,+ lift2, lift3,+ (<*), (*>),+ (<$*), (*$>),+ (<$**), (**$>)+) where++import Prelude hiding ((<*), (*>))+import Control.Applicative hiding ((<*), (*>))++{- $setup+>>> import Control.Flower.Apply++>>> let x = Just 3+>>> let y = Just 4++>>> let f = (+2)+>>> let g = (*2)+>>> let h = (+)+-}++{-| A simple alias for 'Prelude.<*>'++>>> ap (Just (+1)) (Just 4)+Just 5++-}+ap :: Applicative f => f (a -> b) -> f a -> f b+ap = (<*>)++{-| Right-associative, left-flowing applicative operator++>>> Just (+1) <* Just 4+Just 5++-}+infixr 4 <*+(<*) :: Applicative f => f (a -> b) -> f a -> f b+(<*) = ap++{-| Left-associative, right-flowing applicative operator++>>> Just 4 *> Just (+1)+Just 5++-}+infixl 4 *>+(*>) :: Applicative f => f a -> f (a -> b) -> f b+(*>) = flip ap++{-| An alias for 'Control.Applicative.lift2', updating with unified "lift" naming++>>> lift2 (+) (Just 4) (Just 1)+Just 5++-}+lift2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c+lift2 = liftA2++{-| Right-associative, left-flowing 'lift2' operator++>>> (+) <$* Just 4 |< Just 1+Just 5++-}+infixr 4 <$*+(<$*) :: Applicative f => (a -> b -> c) -> f a -> f b -> f c+(<$*) = lift2++{-| Left-associative, right-flowing 'lift2' operator++>>> Just 4 >| Just 1 *$> (+)+Just 5++-}+infixl 4 *$>+(*$>) :: Applicative f => f a -> (a -> b -> c) -> f b -> f c+(*$>) = flip lift2++{-| An alias for 'Control.Applicative.lift3', updating with unified "lift" naming++>>> lift3 (\x y z -> x * y * z) (Just 4) (Just 3) (Just 2)+Just 24++-}+lift3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d+lift3 = liftA3++{-| Right-associative, left-flowing 'lift3' operator++>>> (\x y z -> x * y * z) <$** Just 4 |< Just 3 |< Just 2+Just 24++-}+infixr 4 <$**+(<$**) :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d+f <$** x = \y z -> lift3 f x y z -- AKA f <$ a <* b <* c++{-| Left-associative, right-flowing 'lift3' operator++>>> Just 2 >| Just 3 >| Just 4 **$> \x y z -> x * y * z+Just 24++-}+infixl 4 **$>+(**$>) :: Applicative f => f a -> (a -> b -> c -> d) -> f b -> f c -> f d+x **$> f = \y z -> lift3 f x y z
+ src/Control/Flower/Applicative/Strict.hs view
@@ -0,0 +1,83 @@+{-|+Module : Control.Flower.Applicative.Strict+Description : Combinators for directional strict applicative functors+-}++module Control.Flower.Applicative.Strict (+ lift2',+ (<!$*), (*$!>),+ (<!$**), (**$!>)+) where++import Prelude hiding ((<*), (*>))+import Control.Flower.Functor.Strict+import Control.Flower.Applicative.Lazy++{- $setup+>>> import Control.Flower.Apply++>>> let x = Just 3+>>> let y = Just 4++>>> let f = (+2)+>>> let g = (*2)+>>> let h = (+)+-}++{-| An alias for 'Control.Applicative.lift2', updating with unified "lift" naming++>>> lift2' (+) (Just 4) (Just 1)+Just 5++-}+lift2' :: Monad m => (a -> b -> c) -> m a -> m b -> m c+lift2' f a b = (f <!$ a) <* b++{-| Right-associative, left-flowing `lift2'` operator++>>> (+) <!$* Just 4 |< Just 1+Just 5++-}+infixr 4 <!$*+(<!$*) :: Monad m => (a -> b -> c) -> m a -> m b -> m c+f <!$* a = \b -> lift2' f a b++{-| Left-associative, right-flowing `lift2'` operator++>>> Just 1 >| Just 4 *$!> (+)+Just 5++-}+infixl 4 *$!>+(*$!>) :: Monad m => m a -> (a -> b -> c) -> m b -> m c+a *$!> f = \b -> lift2' f a b++{-| A strict version of 'Control.Flower.Applicative.Lazy.lift3'++>>> lift3' (\x y z -> x * y * z) (Just 4) (Just 3) (Just 2)+Just 24++-}+lift3' :: Monad m => (a -> b -> c -> d) -> m a -> m b -> m c -> m d+lift3' f a b c = ((f <!$ a) <* b) <* c++{-| Right-associative, left-flowing `lift3'` operator++>>> (\x y z -> x * y * z) <!$** Just 4 |< Just 3 |< Just 2+Just 24++-}+infixr 4 <!$**+(<!$**) :: Monad m => (a -> b -> c -> d) -> m a -> m b -> m c -> m d+f <!$** x = \y z -> lift3' f x y z -- AKA f <$ a <* b <* c++{-| Left-associative, right-flowing `lift3'` operator++>>> Just 2 >| Just 3 >| Just 4 **$!> \x y z -> x * y * z+Just 24++-}+infixl 4 **$!>+(**$!>) :: Monad m => m a -> (a -> b -> c -> d) -> m b -> m c -> m d+x **$!> f = \y z -> lift3' f x y z
+ src/Control/Flower/Apply.hs view
@@ -0,0 +1,7 @@+module Control.Flower.Apply (+ module Control.Flower.Apply.Lazy,+ module Control.Flower.Apply.Strict+) where++import Control.Flower.Apply.Lazy+import Control.Flower.Apply.Strict
+ src/Control/Flower/Apply/Lazy.hs view
@@ -0,0 +1,101 @@+{-|+Module : Control.Flower.Apply.Lazy+Description : Combinators for directional lazy application+-}++module Control.Flower.Apply.Lazy (+ (<|), (|>),+ (|<), (>|)+) where++{- $setup+>>> let x = 3+>>> let y = 4++>>> let f = (+2)+>>> let g = (*2)+>>> let h = (+)+-}++{-| Left-flowing application, equivalent to 'prelude.$'.++Read as "backwards application", "pipe from", or "pull from".++>>> (f <| x) == f x+True++>>> (g <| f <| x) == g (f x)+True++This operator can be chained together to show the dataflow through a series of functions++>>> negate <| succ <| 3 :: Int+-4++-}+infixr 0 <|+(<|) :: (a -> b) -> a -> b+f <| x = f x++{-| Right-flowing application, equivalent to 'prelude.$'.++Read as "forwards application" or "pipe into".++>>> (x |> f) == f x+True++>>> (x |> f |> g) == g (f x)+True++This operator can be chained together to show the dataflow through a series of functions++>>> 3 |> succ |> negate :: Int+-4++-}+infixl 0 |>+(|>) :: a -> (a -> b) -> b+x |> f = f x++{-| Left-flowing, left-associative application++Read as "pipe into the result of".+It may seem odd in trivial cases, but is useful for functions that take more than one argument,+as it will partially apply arguments one at a time.++>>> (f |< x) == f x+True++>>> (h |< y |< x) == ((h <| y) <| x)+True++Can be chained together to show the dataflow through a series of functions++>>> (+) |< 3 |< 5 :: Int+8++-}+infixl 0 |<+(|<) :: (a -> b) -> a -> b+(|<) = (<|)++{-| Right-flowing, right-associative application++Read as "pipe from the result of", or "pull from the result from".+It may seem odd in trivial cases, but is useful for functions that take more than one argument.++>>> (x >| f) == f x+True++>>> (x >| y >| h) == (x |> (y |> h))+True++Can be chained together to show the dataflow through a series of functions++>>> 3 >| 5 >| (+)+8++-}+infixr 0 >|+(>|) :: a -> (a -> b) -> b+(>|) = (|>)
+ src/Control/Flower/Apply/Strict.hs view
@@ -0,0 +1,102 @@+{-|+Module : Control.Flower.Apply.Strict+Description : Combinators for directional lazy application+-}+module Control.Flower.Apply.Strict (+ (<!), (!>),+ (!<), (>!)+) where++{- $setup+>>> let x = 3+>>> let y = 4++>>> let f = (+2)+>>> let g = (*2)+>>> let h = (+)+-}+++{-| Left-flowing strict application, equivalent to 'prelude.$'.++Read as "backwards strict application", "strict pipe from", or "strict pull from".++>>> (f <! x) == f x+True++>>> (g <! f <! x) == g (f x)+True++This operator can be chained together to show the dataflow through a series of functions++>>> negate <! succ <! 3 :: Int+-4++-}+infixl 0 !>+(!>) :: a -> (a -> b) -> b+x !> f = f $! x++{-| Right-flowing strict application, equivalent to 'prelude.$'.++Read as "forward strict application" or "strict pipe into".++>>> (x !> f) == f x+True++>>> (x !> f !> g) == g (f x)+True++This operator can be chained together to show the dataflow through a series of functions++>>> 3 !> succ !> negate :: Int+-4++-}+infixr 0 <!+(<!) :: (a -> b) -> a -> b+f <! x = f $! x++{-| Left-flowing, left-associative strict application++Read as "strictly pipe into the result of".+It may seem odd in trivial cases, but is useful for functions that take more than one argument,+as it will partially apply arguments one at a time.++>>> (f !< x) == f x+True++>>> (h !< y !< x) == ((h <! y) <! x)+True++Can be chained together to show the dataflow through a series of functions++>>> (+) !< 3 !< 5 :: Int+8++-}++infixl 1 !<+(!<) :: (a -> b) -> a -> b+(!<) = (<!)++{-| Right-flowing, right-associative strict application++Read as "strictly pipe from the result of", or "strictly pull from the result from".+It may seem odd in trivial cases, but is useful for functions that take more than one argument.++>>> (x >! f) == f x+True++>>> (x >! y >! h) == (x !> (y !> h))+True++Can be chained together to show the dataflow through a series of functions++>>> 3 >! 5 >! (+)+8++-}+infixr 1 >!+(>!) :: a -> (a -> b) -> b+(>!) = (!>)
+ src/Control/Flower/Compose.hs view
@@ -0,0 +1,48 @@+{-|+Module : Control.Flower.Compose+Description : Directional composition combinators+-}+module Control.Flower.Compose ((<.), (.>)) where++{- $setup+>>> import Control.Flower.Apply.Lazy++>>> let x = 3+>>> let y = 4++>>> let f = (+2)+>>> let g = (*2)+>>> let h = (+)+-}++{-| Right-flowing, left-associative composition++Note that this is the opposite direction from typical composition++>>> (f .> g) x == (g . f) x+True++Can be combined with application combinators++>>> 5 |> (+1) .> (*10) :: Int+60++-}+infixl 9 .>+(.>) :: (a -> b) -> (b -> c) -> a -> c+a .> b = b . a++{-| Left-flowing, right-associative composition++>>> (g <. f) x == (g . f) x+True++Can be combined with application combinators++>>> (+1) <. (*10) <| 5 :: Int+51++-}+infixr 9 <.+(<.) :: (b -> c) -> (a -> b) -> a -> c+b <. a = b . a
+ src/Control/Flower/Functor.hs view
@@ -0,0 +1,7 @@+module Control.Flower.Functor (+ module Control.Flower.Functor.Lazy,+ module Control.Flower.Functor.Strict+) where++import Control.Flower.Functor.Lazy+import Control.Flower.Functor.Strict
+ src/Control/Flower/Functor/Lazy.hs view
@@ -0,0 +1,78 @@+{-|+Module : Control.Flower.Functor.Lazy+Description : Lazy functor combinators+-}++module Control.Flower.Functor.Lazy (lift, over, (<$), ($>)) where++import Prelude hiding ((<$))+import Flow ((<|))++-- $setup+-- >>> import Flow ((|>), (<.), (.>))++{-| Rename `fmap` to `lift` for consistency++>>> lift (+1) <| Just 0+Just 1++>>> lift (lift (+1)) [[1,2,3],[4,5,6]]+[[2,3,4],[5,6,7]]++-}+lift :: Functor f => (a -> b) -> f a -> f b+lift = fmap++{-| Alias for `apply`, for readability (especially when teaching)++>>> lift (+1) `over` Just 0+Just 1++>>> Just 0 $> (+1) $> (+2)+Just 3++>>> (*2) <$ ([1,2,3] $> (+1))+[4,6,8]++>>> (+8) .> (*2) <$ Just 0+Just 16++>>> (*3) <. (+8) <$ Just 0+Just 24++-}+over :: (a -> b) -> a -> b+over = (<|)++infixr 4 <$+{-| Operator for `lift` highlighting the direction of data flow++>>> (+1) <$ Just 0+Just 1++>>> (+2) <$ (+1) <$ Just 0+Just 3+++>>> ((*2) <$ [1,2,3]) $> (+1)+[3,5,7]++>>> Just 0 $> (+8) .> (*2)+Just 16++>>> Just 0 $> (*3) <. (+8)+Just 24++-}+(<$) :: Functor f => (a -> b) -> f a -> f b+(<$) = lift++infixl 4 $>+{-| Operator for `lift` highlighting the reversed direction of data flow++>>> Just 0 $> (+1)+Just 1++-}+($>) :: Functor f => f a -> (a -> b) -> f b+($>) = flip lift
+ src/Control/Flower/Functor/Strict.hs view
@@ -0,0 +1,58 @@+{-|+Module : Control.Flower.Functor.Strict+Description : Strict functor combinators (requires a monad instance)+-}++module Control.Flower.Functor.Strict (+ lift',+ over',+ (<!$),+ ($!>)+) where++import Control.Flower.Apply ((<!))+import Control.Monad ((<$!>))++-- $setup+-- >>> import Flow ((<|))++{- | A strict version of `lift`++>>> lift' (+1) <| Just 0+Just 1++>>> lift' (lift' (+1)) [[1,2,3],[4,5,6]]+[[2,3,4],[5,6,7]]++-}+lift' :: Monad m => (a -> b) -> m a -> m b+lift' = (<$!>)++{- | Alias for `apply'`, for readability (especially when teaching)++>>> lift' (+1) `over'` Just 0+Just 1++-}+over' :: (a -> b) -> a -> b+over' = (<!)++{- | Operator for `lift'` highlighting the direction of data flow++>>> (+1) <!$ Just 0+Just 1++-}+infixr 4 <!$+(<!$) :: Monad f => (a -> b) -> f a -> f b+(<!$) = lift'++{- | Operator for `lift'` highlighting the reversed direction of data flow++>>> Just 0 $!> (+1)+Just 1++-}+infixl 4 $!>+($!>) :: Monad f => f a -> (a -> b) -> f b+($!>) = flip lift'
+ src/Control/Flower/Monad.hs view
@@ -0,0 +1,63 @@+{-|+Module : Control.Flower.Monad+Description : Combinators for directional monadic mapping+-}+module Control.Flower.Monad (+ (<<$), ($>>),+ (=<<$), ($>>=)+) where++{- $setup+>>> import Control.Flower.Compose++>>> let x = Just 3+>>> let y = Just 4++>>> let f = (+2)+>>> let g = (*2)+>>> let h = (+)+-}++{-| A left-associative operator alias for 'Control.Monad.mapM'++>>> putStrLn <. show <<$ [1,2,3]+1+2+3++-}+infixl 4 <<$+(<<$) :: (Foldable f, Monad m) => (a -> m b) -> f a -> m ()+(<<$) = mapM_++{-| An operator alias for 'Control.Monad.mapM'++>>> [1,2,3] $>> show .> putStrLn+1+2+3++-}+infixr 4 $>>+($>>) :: (Foldable f, Monad m) => f a -> (a -> m b) -> m ()+($>>) = flip mapM_++{-| A left-associative operator alias for 'Control.Monad.mapM'++>>> (\x -> [x+1]) =<<$ [1,2,3]+[[2,3,4]]++-}+infixl 4 =<<$+(=<<$) :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)+(=<<$) = mapM++{-| An operator alias for 'Control.Monad.mapM'++>>> [1,2,3] $>>= \x -> [x+1]+[[2,3,4]]++-}+infixr 4 $>>=+($>>=) :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)+($>>=) = flip mapM
+ test/doctests.hs view
@@ -0,0 +1,19 @@+module Main where++import Test.DocTest++main :: IO ()+main = doctest [ "-isrc"+ , "src/Control/Flower/Apply/Lazy.hs"+ , "src/Control/Flower/Apply/Strict.hs"++ , "src/Control/Flower/Compose.hs"++ , "src/Control/Flower/Functor/Lazy.hs"+ , "src/Control/Flower/Functor/Strict.hs"++ , "src/Control/Flower/Applicative/Lazy.hs"+ , "src/Control/Flower/Applicative/Strict.hs"++ , "src/Control/Flower/Monad.hs"+ ]