Configure the rule, determining how automatic fixes are generated.
The default Configs fixInArgument and
fixInLet should be used as reasonable defaults, with more
customization detailed in those sections.
The behavior of the rule in the context of useless single pattern cases can also
be configured via replaceUnusedBindings. A single
pattern case is considered to be useless if its pattern does not bind any name
that is actually used in the expression.
Always fix by destructuring in the argument. This will use as patterns if
necessary. If the argument cannot be destructured in, no fix will be generated.
For example:
f1 o =
case o of
Opaque i ->
i
f2 o =
let
x =
someFunc o
in
case o of
Opaque i ->
i + x
f3 { recordField } =
case recordField of
Opaque i ->
iwill be fixed to:
f1 (Opaque i) =
i
f2 ((Opaque i) as o) =
let
x =
someFunc o
in
i + x
f3 { recordField } =
case recordField of
Opaque i ->
iUse ifAsPatternRequired and
ifCannotDestructureAtArgument to customize
the behavior in either of these cases.
Always fix by destructuring in a let block, creating a new one if none
exists.
For example:
f1 o =
case o of
Opaque i ->
i
f2 o =
let
x =
someFunc o
in
case o of
Opaque i ->
i + xwill be fixed to:
f1 o =
let
(Opaque i) =
o
in
i
f2 ((Opaque i) as o) =
let
x =
someFunc o
(Opaque i) =
o
in
i + xUse ifNoLetExists to customize the behavior in the case
where no let block exists within the scope the pattern is valid in. To
clarify, the following counts as no let existing:
unpack : Opaque -> Int
unpack o =
let
foo =
bar
in
(\a ->
case a of
Opaque i ->
i
)
oas the name a is not in scope in the extant let block.
ifNoLetExists also handles the case where the closest let
block would result in a name clash. To clarify, the following counts as no
let existing:
unpack : Opaque -> Int
unpack o =
let
foo =
(\i -> i + 1) 0
in
case o of
Opaque i ->
ias i cannot be unpacked in the let block, as doing so would cause a name
clash with the i in foo.
A single pattern case is considered to be useless if its pattern does not bind any name that is actually used in the expression, e.g.
case x of
_ ->
True
case x of
() ->
True
case x of
A ({ field1, field2 } as record) ->
List.map foo bar
|> List.sum
|> bazThe rule will always provide fixes for such cases but by default will not
replace the binding used in the case...of expression. This option configures
the rule to replace such bindings where possible. Fox example:
f unusedArg =
case unusedArg of
_ ->
Truewill be fixed to
f _ =
TrueThis provides a more clear indication that the binding is unused. The binding
will of course not be replaced if it used anywhere but in case...of.
Specify what to do if an as pattern would be required to destructure in
the argument, e.g.
f o =
let
x =
someFunc o
in
case o of
Opaque i ->
i + xAvailable options are useAsPattern (this is the default),
fixInLetInstead or fail,
e.g.
c1 =
fixInArgument
|> ifAsPatternRequired fail
c2 =
fixInArgument
|> ifAsPatternRequired useAsPattern
c3 =
fixInArgument
|> ifAsPatternRequired
(fixInLetInstead
|> andIfNoLetExists createNewLet
)
c4 =
fixInArgument
|> ifAsPatternRequired
(fixInLetInstead
|> andIfNoLetExists useAsPattern
)Specify what to do if the argument cannot be destructured at, either due to it being a record field, e.g.
f { recordField } =
case recordField of
Opaque i ->
ior a more complex case expression, e.g.
f a =
case foo <| bar a of
Opaque i ->
ior due to a name clash that would be caused by the increase in scope, e.g.
unpack : Opaque -> Int
unpack o =
let
foo =
(\i -> i + 1) 0
in
case o of
Opaque i ->
iAvailable options are fixInLetInstead or fail
(this is the default).
c1 =
fixInArgument
|> ifCannotDestructureAtArgument fail
c2 =
fixInArgument
|> ifCannotDestructureAtArgument
(fixInLetInstead
|> andIfNoLetExists fail
)
c3 =
fixInArgument
|> ifCannotDestructureAtArgument
(fixInLetInstead
|> andIfNoLetExists createNewLet
)Specify what to do it no let block exists in scope, instead of creating a
new one.
Available options are fixInArgumentInstead,
createNewLet (this is the default), or fail. Note
that andIfAsPatternRequired and
andIfCannotDestructureAtArgument must appear
in that order after fixInArgumentInstead.
c1 =
fixInLet
|> ifNoLetExists fail
c2 =
fixInLet
-- This is the default
|> ifNoLetExists createNewLet
c3 =
fixInLet
|> ifNoLetExists
(fixInArgumentInstead
|> andIfAsPatternRequired useAsPattern
|> andIfCannotDestructureAtArgument fail
)These functions are simply used by
ifAsPatternRequired,
ifCannotDestructureAtArgument, and
ifNoLetExists to customize behavior of the default configs.
Look at the examples in those to understand how to use them.
Choose to create a let block when none exists.
Choose to use an as pattern to destructure in the argument if necessary.
Fallback to destructuring in the argument instead of a let block.
Note that andIfAsPatternRequired and
andIfCannotDestructureAtArgument must appear
in that order, e.g.
c =
fixInLet
|> ifNoLetExists
(fixInArgumentInstead
|> andIfAsPatternRequired useAsPattern
|> andIfCannotDestructureAtArgument fail
)Specify what to do if an as pattern would be necessary.
Available options are useAsPattern,
createNewLet or fail
c1 =
fixInLet
|> ifNoLetExists
(fixInArgumentInstead
|> andIfAsPatternRequired useAsPattern
|> andIfCannotDestructureAtArgument fail
)
c2 =
fixInLet
|> ifNoLetExists
(fixInArgumentInstead
|> andIfAsPatternRequired createNewLet
|> andIfCannotDestructureAtArgument fail
)
c3 =
fixInLet
|> ifNoLetExists
(fixInArgumentInstead
|> andIfAsPatternRequired fail
|> andIfCannotDestructureAtArgument fail
)Specify what to do if the argument cannot be destructured at, e.g.
f { recordField } =
case recordField of
Opaque i ->
iAvailable options are createNewLet or fail
c1 =
fixInLet
|> ifNoLetExists
(fixInArgumentInstead
|> andIfAsPatternRequired fail
|> andIfCannotDestructureAtArgument createNewLet
)
c2 =
fixInLet
|> ifNoLetExists
(fixInArgumentInstead
|> andIfAsPatternRequired fail
|> andIfCannotDestructureAtArgument fail
)Fallback to destructuring in a let block instead of the argument.
If no let block exists to destructure in, choose some other behavior
instead.
You shouldn't need to worry about these types; they are exported solely for the sake of annotation, should it be necessary.
Phantom type for Config fixBy.
Phantom type for Config fixBy.
Fallback to destructuring in the argument, if choosing not to create a let
block.
Fallback to using a let block if destructuring in the argument has failed
(or we've chosen not to).
Choose to create a new let block to destructure in.
Choose to fail at generating a fix.
Choose to use an as pattern.
At this point, an as pattern could be used or some other option.
At this point, a new let could be created or some other option.
At this point, the argument could be used or a new let block created.
block.
At this point, a let could be used or either of two other options.
At this point, the only option is to use a let block.
At this point, an as pattern could be used, or we could use a let block.
Offer a choice between two options.
Reports single-pattern case expressions, which may be written more concisely or removed entirely.
See
Configfor configuration details.Fail
Single-pattern case expressions for destructuring are not allowed, as:
may instead be written more concisely, for example as
Similarly, single-pattern case expressions that ase not used for destructuring are not allowed, as:
may instead be written more concisely, for example as
or
Success
Any case expression with more than one pattern match will not be reported. Consider using
jfmengels/elm-review-simplifyto detect unnecessary multi-pattern cases.When (not) to enable this rule
This rule is useful if you prefer destructuring in function/lambda arguments or
letbindings, rather than in a single-pattern case.This rule is not useful if you prefer the more verbose style.
Try it out
You can try this rule out by running the following command: