Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inlining? #35

Open
ratherforky opened this issue Apr 11, 2024 · 2 comments
Open

Inlining? #35

ratherforky opened this issue Apr 11, 2024 · 2 comments

Comments

@ratherforky
Copy link

I love this library and use it in basically every Haskell project, I just have one quibble: inlining

In Prelude, the source code for (.) is:

{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

But (.>), (<.), (|>) etc. in Flow don't have any inline pragmas. I only checked this because (|>) showed up as a non-zero cost centre in some code I was profiling and I was surprised.

Changing the library to inline nicely should be fairly straightforward and I'd be happy to make a pull request for it. It'd mostly be a case of adding inline pragmas for everything, with the biggest change being compose f g x = g (f x) to compose f g = \x -> g (f x) for the same reason (.) is like that.12

Footnotes

  1. Moreover, GHC will only inline the function if it is fully applied, where “fully applied” means applied to as many arguments as appear (syntactically) on the LHS of the function definition.

  2. I only learned about this behaviour after asking r/haskell to explain some surprising performance of foldl' and patching it in base

@tfausak
Copy link
Owner

tfausak commented Apr 12, 2024

👍 I'd happily accept a PR for improving performance. Bonus points for a benchmark that actually shows the improvement.

@tfausak
Copy link
Owner

tfausak commented Apr 15, 2024

I wonder if it would be sufficient to change how these operators are defined. The current definitions are perhaps overly verbose.

-- current
x |> f = apply x f
f <| x = apply x f
apply x f = f x

f .> g = compose f g
g <. f = compose f g
compose f g x = g (f x)

x !> f = apply' x f
f <! x = apply' x f
apply' x f = seq x (apply x f)
-- could be
(|>) = apply
(<|) = flip apply
apply = (Data.Function.&)
-- or flip ($)
-- neither (&) nor flip have INLINE pragmas

(.>) = compose
(<.) = flip compose
compose = (Control.Category.>>>)
-- or flip (.)
-- "Note [INLINE on >>>]" https://hackage.haskell.org/package/base-4.19.1.0/docs/src/Control.Category.html#line-82

(!>) = apply'
(<!) = flip apply'
apply' = flip ($!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants