Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion data/hlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@
- hint: {lhs: any (const True) x, rhs: not (null x), name: Use null}
- hint: {lhs: length x /= 0, rhs: not (null x), note: IncreasesLaziness, name: Use null}
- hint: {lhs: 0 /= length x, rhs: not (null x), note: IncreasesLaziness, name: Use null}
- hint: {lhs: "\\x -> [x]", rhs: "(:[])", name: "Use :"}
# Moved to code-based hint in Hint/List.hs to skip under OverloadedLists (issue #1602)
# - hint: {lhs: "\\x -> [x]", rhs: "(:[])", name: "Use :"}
- hint: {lhs: map f (zip x y), rhs: zipWith (curry f) x y, side: not (isApp f)}
- hint: {lhs: "map f (fromMaybe [] x)", rhs: "maybe [] (map f) x"}
- hint: {lhs: "concatMap f (fromMaybe [] x)", rhs: "maybe [] (concatMap f) x"}
Expand Down
18 changes: 18 additions & 0 deletions src/Hint/List.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ foo = [_ | x <- _, let _ = A{x}]
issue1039 = foo (map f [1 | _ <- []]) -- [f 1 | _ <- []]
{-# LANGUAGE OverloadedLists #-} \
issue114 = True:[]
{-# LANGUAGE OverloadedLists #-} \
no_issue1602 = \x -> [x]
yes_issue1602 = \x -> [x] -- (:[])
</TEST>
-}

Expand Down Expand Up @@ -188,6 +191,7 @@ checks overloadedListsOn = let (*) = (,) in drop1 -- see #174
, "Use :" * useCons
]
<> ["Use list literal" * useList | not overloadedListsOn ] -- see #114
<> ["Use :" * useConsLambda | not overloadedListsOn ] -- see #1602

pchecks :: [(String, LPat GhcPs -> Maybe (LPat GhcPs, [(String, R.SrcSpan)], String))]
pchecks = let (*) = (,) in drop1 -- see #174
Expand Down Expand Up @@ -263,6 +267,20 @@ useCons False (view -> App2 op x y) | varToStr op == "++"
gen x = noLocA . OpApp noExtField x (noLocA (HsVar noExtField (noLocA consDataCon_RDR)))
useCons _ _ = Nothing

-- Suggest `(: [])` for `\x -> [x]`. Gated on `not overloadedListsOn`
-- because under OverloadedLists the literal `[x]` can be polymorphic
-- (e.g. Vector a, Set a, NonEmpty a), whereas `(: [])` specialises
-- to the list type and the rewrite produces code that no longer
-- type-checks (issue #1602).
useConsLambda :: Bool -> LHsExpr GhcPs -> Maybe (LHsExpr GhcPs, [(String, R.SrcSpan)], String)
useConsLambda _ (SimpleLambda [view -> PVar_ x] (L _ (ExplicitList _ [L _ (HsVar _ (L _ y))])))
| occNameStr y == x =
let consSection = noLocA (HsPar noAnn (noLocA (SectionR noExtField
(noLocA (HsVar noExtField (noLocA consDataCon_RDR)))
(noLocA (ExplicitList noAnn [])))))
in Just (consSection, [], "(: [])")
useConsLambda _ _ = Nothing

typeListChar :: LHsType GhcPs
typeListChar =
noLocA $ HsListTy noAnn
Expand Down