jsuder-xx/elm-review-reducible-lambdas/1.0.1

NOTE: the latest version is 2.0.1

NoEtaReducibleLambdas

Provides elm-review rules to detect reducible lambda expressions using different techniques.

This rule detect reducible lambda expressions using different techniques.

Fail

example1 =
    List.map (\a -> f a)


example2 =
    List.map (\a -> f (g 10) a)

Success

example1 =
    List.map f


example2 =
    List.map (f (g 10))

When (not) to enable this rule

This rule can change the performance characteristics of your program which is why LambdaReduceStrategy offers different levels of reduction.

  • Reducing \\a b -> f a b to f

    • If f does work on first argument
    • Then this modification will cause that work to be done immediately on first application
    • Whereas behind the lambda it would wait until the second argument.
  • Reducing \\a b -> f g a b to f g

    • Causes an immediate application but no computation on arguments.
    • If f does work on first argument
    • Then this will cause that work to be done immediately at this location
    • And if f does work on second argument
    • Then this reduction will cause this work to be done on application of second argument.
    • Whereas behind this lambda the application of g and a to f would wait until b had been applied.
  • Reducing \\a b -> f (g 10) a b to f (g 10)

    • Causes g 10 to evaluate immediately which could be costly
    • In addition to every other change indicated in the prior reduction example.

Configuration

module ReviewConfig exposing (config)


import NoEtaReducibleLambdas
import Review.Rule exposing (Rule)


config : List Rule
config =
    [ NoEtaReducibleLambdas.rule NoEtaReducibleLambdas.AlwaysRemoveLambdaWhenPossible
    ]

Try it out

You can try this rule out by running the following command:

elm-review --template jsuder-xx/elm-review-eta-reduction/example --rules NoEtaReducibleLambdas
= RemoveLambdaWhenNoCallsInApplication
| OnlyWhenSingleArgument
| AlwaysRemoveLambdaWhenPossible

Use these to control how aggressively lambda expressions are reduced.

  • OnlyWhenSingleArgument has the least impact on performance and will reduce the least.

    • This will reduce \a -> f a to f.
    • It will not reduce \a -> (getFunction 10) a because there is a function application to get the function.
  • RemoveLambdaWhenNoCallsInApplication should have minimal impact on performance and reduces most of the functions you would want to reduce.

    • This will reduce \a -> f a to f.
    • This will reduce \a b -> f a b to f.
    • This will reduce \a b -> f [1, 2, 3] a b to f [1, 2, 3]
    • This will reduce \a b -> f (g 10) a b to \a -> f (g 10) a but it will not remove the lambda outright because of the (g 10) call.
    • This will reduce \a b c -> a b c to identity.
    • This will not reduce \a -> f (g 10) a due to the (g 10) call.
  • AlwaysRemoveLambdaWhenPossible is the most aggressive.

    • This will reduce \a -> f a to f.
    • This will reduce \a b -> f a b to f.
    • This will reduce \a b -> f [1, 2, 3] a b to f [1, 2, 3]
    • This will reduce \a b -> f (g 10) a b to f (g 10).
    • This will reduce \a b c -> a b c to identity.
    • This will reduce \a -> (getFunction 10) a to (getFunction 10).

See the module documentation.

canRemoveLambda : ErrorMessage

Error message when the lambda can be removed (for unit testing only).

canRemoveSomeArguments : ErrorMessage

Error message when arguments can be removed (for unit testing only).

reducesToIdentity : ErrorMessage

Error message when the lambda reduces to identity (for unit testing only).