module Hint.Lambda where
import HSE.All
import Hint.Util
import Type
import Hint
import Util
lambdaHint :: DeclHint
lambdaHint _ _ x = concatMap lambdaExp (universeBi x) ++ concatMap lambdaDecl (universe x)
lambdaDecl :: Decl_ -> [Idea]
lambdaDecl o@(FunBind _ [Match _ name pats (UnGuardedRhs _ bod) Nothing])
| Lambda _ vs y <- bod = [err "Redundant lambda" o $ reform (pats++vs) y]
| (pats2,bod2) <- etaReduce pats bod, length pats2 < length pats = [err "Eta reduce" o $ reform pats2 bod2]
where reform p b = FunBind an [Match an name p (UnGuardedRhs an b) Nothing]
lambdaDecl _ = []
etaReduce :: [Pat_] -> Exp_ -> ([Pat_], Exp_)
etaReduce ps (App _ x (Var _ (UnQual _ (Ident _ y))))
| ps /= [], PVar _ (Ident _ p) <- last ps, p == y, p /= "mr", y `notElem` vars x
= etaReduce (init ps) x
etaReduce ps x = (ps,x)
lambdaExp :: Exp_ -> [Idea]
lambdaExp o@(Paren _ (App _ (Var _ (UnQual _ (Symbol _ x))) y)) | isAtom y, allowLeftSection x =
[warn "Use section" o $ LeftSection an y (toNamed x)]
lambdaExp o@(Paren _ (App _ (App _ (view -> Var_ "flip") (Var _ x)) y)) | allowRightSection $ fromNamed x =
[warn "Use section" o $ RightSection an (QVarOp an x) y]
lambdaExp o@Lambda{} | res <- niceLambda [] o, not $ isLambda res =
[warn "Avoid lambda" o res]
lambdaExp o@(Lambda _ ps1 (fromParen -> Lambda _ ps2 bod)) | pvars ps1 `disjoint` pvars ps2 =
[warn "Collapse lambdas" o $ Lambda an (ps1++ps2) bod]
lambdaExp _ = []