Provides elm-review
rules to detect reducible lambda expressions using different techniques.
rule : Config -> Review.Rule.Rule
This rule detect reducible lambda expressions using different techniques.
example1 =
List.map (\a -> f a)
example2 =
List.map (\a -> f (g 10) a)
example1 =
List.map f
example2 =
List.map (f (g 10))
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
f
does work on first argumentReducing \\a b -> f g a b
to f g
f
does work on first argumentf
does work on second argumentg
and a
to f
would wait until b
had been applied.Reducing \\a b -> f (g 10) a b
to f (g 10)
g 10
to evaluate immediately which could be costlymodule ReviewConfig exposing (config)
import NoEtaReducibleLambdas
import Review.Rule exposing (Rule)
-- Below is an example of the strongest configuration. It will reduce the most.
config : List Rule
config =
[ NoEtaReducibleLambdas.rule
{ lambdaReduceStrategy = NoEtaReducibleLambdas.AlwaysRemoveLambdaWhenPossible
, argumentNamePredicate = always True
}
]
-- Conservative configuration: Only reduces single argument lambdas with a single letter argument name.
conservativeConfig : List Rule
conservativeConfig =
[ NoEtaReducibleLambdas.rule
{ lambdaReduceStrategy = NoEtaReducibleLambdas.OnlyWhenSingleArgument
, argumentNamePredicate = \argumentName -> String.length argumentName <= 1
}
]
You can try this rule out by running the following command:
elm-review --template jsuder-xx/elm-review-eta-reduction/example --rules NoEtaReducibleLambdas
Control how aggressively lambda expressions are reduced.
OnlyWhenSingleArgument has the least impact on performance and will reduce the least.
\a -> f a
to f
.\a b -> f a b
because there are two arguments.\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.
\a -> f a
to f
.\a b -> f a b
to f
.\a b -> f [1, 2, 3] a b
to f [1, 2, 3]
\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.\a b c -> a b c
to identity
.\a -> f (g 10) a
due to the (g 10)
call.AlwaysRemoveLambdaWhenPossible is the most aggressive.
\a -> f a
to f
.\a b -> f a b
to f
.\a b -> f [1, 2, 3] a b
to f [1, 2, 3]
\a b -> f (g 10) a b
to f (g 10)
.\a b c -> a b c
to identity
.\a -> (getFunction 10) a
to (getFunction 10)
.See the module documentation.
{ argumentNamePredicate : String -> Basics.Bool
, lambdaReduceStrategy : LambdaReduceStrategy
}
Configuration options for determining under what circumstances this rule will perform a reduction.
\argumentName -> String.length argumentName == 1
.always True
.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).