{-
(c) The University of Glasgow 2011

-}

{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}

-- | The deriving code for the Functor, Foldable, and Traversable classes
module GHC.Tc.Deriv.Functor
   ( FFoldType(..)
   , functorLikeTraverse
   , deepSubtypesContaining
   , foldDataConArgs

   , gen_Functor_binds
   , gen_Foldable_binds
   , gen_Traversable_binds
   )
where

#include "GhclibHsVersions.h"

import GHC.Prelude

import GHC.Data.Bag
import GHC.Core.DataCon
import GHC.Data.FastString
import GHC.Hs
import GHC.Utils.Panic
import GHC.Builtin.Names
import GHC.Types.Name.Reader
import GHC.Types.SrcLoc
import GHC.Utils.Monad.State
import GHC.Tc.Deriv.Generate
import GHC.Tc.Utils.TcType
import GHC.Core.TyCon
import GHC.Core.TyCo.Rep
import GHC.Core.Type
import GHC.Utils.Misc
import GHC.Types.Var
import GHC.Types.Var.Set
import GHC.Types.Id.Make (coerceId)
import GHC.Builtin.Types (true_RDR, false_RDR)

import Data.Maybe (catMaybes, isJust)

{-
************************************************************************
*                                                                      *
                        Functor instances

 see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html

*                                                                      *
************************************************************************

For the data type:

  data T a = T1 Int a | T2 (T a)

We generate the instance:

  instance Functor T where
      fmap f (T1 b1 a) = T1 b1 (f a)
      fmap f (T2 ta)   = T2 (fmap f ta)

Notice that we don't simply apply 'fmap' to the constructor arguments.
Rather
  - Do nothing to an argument whose type doesn't mention 'a'
  - Apply 'f' to an argument of type 'a'
  - Apply 'fmap f' to other arguments
That's why we have to recurse deeply into the constructor argument types,
rather than just one level, as we typically do.

What about types with more than one type parameter?  In general, we only
derive Functor for the last position:

  data S a b = S1 [b] | S2 (a, T a b)
  instance Functor (S a) where
    fmap f (S1 bs)    = S1 (fmap f bs)
    fmap f (S2 (p,q)) = S2 (a, fmap f q)

However, we have special cases for
         - tuples
         - functions

More formally, we write the derivation of fmap code over type variable
'a for type 'b as ($fmap 'a 'b x).  In this general notation the derived
instance for T is:

  instance Functor T where
      fmap f (T1 x1 x2) = T1 ($(fmap 'a 'b1) x1) ($(fmap 'a 'a) x2)
      fmap f (T2 x1)    = T2 ($(fmap 'a '(T a)) x1)

  $(fmap 'a 'b x)          = x     -- when b does not contain a
  $(fmap 'a 'a x)          = f x
  $(fmap 'a '(b1,b2) x)    = case x of (x1,x2) -> ($(fmap 'a 'b1 x1), $(fmap 'a 'b2 x2))
  $(fmap 'a '(T b1 a) x)   = fmap f x -- when a only occurs directly as the last argument of T
  $(fmap 'a '(T b1 b2) x)  = fmap (\y. $(fmap 'a 'b2 y)) x -- when a only occurs in the last parameter, b2
  $(fmap 'a '(tb -> tc) x) = \(y:tb[b/a]) -> $(fmap 'a' 'tc' (x $(cofmap 'a 'tb y)))

For functions, the type parameter 'a can occur in a contravariant position,
which means we need to derive a function like:

  cofmap :: (a -> b) -> (f b -> f a)

This is pretty much the same as $fmap, only without the $(cofmap 'a 'a x) and
$(cofmap 'a '(T b1 a) x) cases:

  $(cofmap 'a 'b x)          = x     -- when b does not contain a
  $(cofmap 'a 'a x)          = error "type variable in contravariant position"
  $(cofmap 'a '(b1,b2) x)    = case x of (x1,x2) -> ($(cofmap 'a 'b1) x1, $(cofmap 'a 'b2) x2)
  $(cofmap 'a '(T b1 a) x)   = error "type variable in contravariant position" -- when a only occurs directly as the last argument of T
  $(cofmap 'a '(T b1 b2) x)  = fmap (\y. $(cofmap 'a 'b2 y)) x -- when a only occurs in the last parameter, b2
  $(cofmap 'a '(tb -> tc) x) = \(y:tb[b/a]) -> $(cofmap 'a' 'tc' (x $(fmap 'a 'tb y)))

Note that the code produced by $(fmap _ _ _) is always a higher order function,
with type `(a -> b) -> (g a -> g b)` for some g.

Note that there are two distinct cases in $fmap (and $cofmap) that match on an
application of some type constructor T (where T is not a tuple type
constructor):

  $(fmap 'a '(T b1 a) x)  = fmap f x -- when a only occurs directly as the last argument of T
  $(fmap 'a '(T b1 b2) x) = fmap (\y. $(fmap 'a 'b2 y)) x -- when a only occurs in the last parameter, b2

While the latter case technically subsumes the former case, it is important to
give special treatment to the former case to avoid unnecessary eta expansion.
See Note [Avoid unnecessary eta expansion in derived fmap implementations].

We also generate code for (<$) in addition to fmap—see Note [Deriving <$] for
an explanation of why this is important. Just like $fmap/$cofmap above, there
is a similar algorithm for generating `p <$ x` (for some constant `p`):

  $(replace 'a 'b x)          = x      -- when b does not contain a
  $(replace 'a 'a x)          = p
  $(replace 'a '(b1,b2) x)    = case x of (x1,x2) -> ($(replace 'a 'b1 x1), $(replace 'a 'b2 x2))
  $(replace 'a '(T b1 a) x)   = p <$ x -- when a only occurs directly as the last argument of T
  $(replace 'a '(T b1 b2) x)  = fmap (\y. $(replace 'a 'b2 y)) x -- when a only occurs in the last parameter, b2
  $(replace 'a '(tb -> tc) x) = \(y:tb[b/a]) -> $(replace 'a' 'tc' (x $(coreplace 'a 'tb y)))

  $(coreplace 'a 'b x)          = x      -- when b does not contain a
  $(coreplace 'a 'a x)          = error "type variable in contravariant position"
  $(coreplace 'a '(b1,b2) x)    = case x of (x1,x2) -> ($(coreplace 'a 'b1 x1), $(coreplace 'a 'b2 x2))
  $(coreplace 'a '(T b1 a) x)   = error "type variable in contravariant position" -- when a only occurs directly as the last argument of T
  $(coreplace 'a '(T b1 b2) x)  = fmap (\y. $(coreplace 'a 'b2 y)) x -- when a only occurs in the last parameter, b2
  $(coreplace 'a '(tb -> tc) x) = \(y:tb[b/a]) -> $(coreplace 'a' 'tc' (x $(replace 'a 'tb y)))
-}

gen_Functor_binds :: SrcSpan -> TyCon -> [Type] -> (LHsBinds GhcPs, BagDerivStuff)
-- When the argument is phantom, we can use  fmap _ = coerce
-- See Note [Phantom types with Functor, Foldable, and Traversable]
gen_Functor_binds :: SrcSpan -> TyCon -> [Type] -> (LHsBinds GhcPs, BagDerivStuff)
gen_Functor_binds SrcSpan
loc TyCon
tycon [Type]
_
  | Role
Phantom <- [Role] -> Role
forall a. [a] -> a
last (TyCon -> [Role]
tyConRoles TyCon
tycon)
  = (Located (HsBindLR GhcPs GhcPs)
-> Bag (Located (HsBindLR GhcPs GhcPs))
forall a. a -> Bag a
unitBag Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
fmap_bind, BagDerivStuff
forall a. Bag a
emptyBag)
  where
    fmap_name :: GenLocated SrcSpan RdrName
fmap_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
fmap_RDR
    fmap_bind :: LHsBind GhcPs
fmap_bind = GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)] -> LHsBind GhcPs
mkRdrFunBind GenLocated SrcSpan RdrName
fmap_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
fmap_eqns
    fmap_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
fmap_eqns = [HsMatchContext (NoGhcTc GhcPs)
-> [LPat GhcPs]
-> Located (HsExpr GhcPs)
-> LMatch GhcPs (Located (HsExpr GhcPs))
forall (p :: Pass) (body :: * -> *).
HsMatchContext (NoGhcTc (GhcPass p))
-> [LPat (GhcPass p)]
-> Located (body (GhcPass p))
-> LMatch (GhcPass p) (Located (body (GhcPass p)))
mkSimpleMatch HsMatchContext GhcPs
HsMatchContext (NoGhcTc GhcPs)
fmap_match_ctxt
                               [LPat GhcPs
nlWildPat]
                               Located (HsExpr GhcPs)
LHsExpr GhcPs
coerce_Expr]
    fmap_match_ctxt :: HsMatchContext GhcPs
fmap_match_ctxt = LIdP GhcPs -> HsMatchContext GhcPs
forall p. LIdP p -> HsMatchContext p
mkPrefixFunRhs GenLocated SrcSpan RdrName
LIdP GhcPs
fmap_name

gen_Functor_binds SrcSpan
loc TyCon
tycon [Type]
tycon_args
  = ([Located (HsBindLR GhcPs GhcPs)]
-> Bag (Located (HsBindLR GhcPs GhcPs))
forall a. [a] -> Bag a
listToBag [Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
fmap_bind, Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
replace_bind], BagDerivStuff
forall a. Bag a
emptyBag)
  where
    data_cons :: [DataCon]
data_cons = TyCon -> [Type] -> [DataCon]
getPossibleDataCons TyCon
tycon [Type]
tycon_args
    fmap_name :: GenLocated SrcSpan RdrName
fmap_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
fmap_RDR

    -- See Note [EmptyDataDecls with Functor, Foldable, and Traversable]
    fmap_bind :: LHsBind GhcPs
fmap_bind = Arity
-> (LHsExpr GhcPs -> LHsExpr GhcPs)
-> GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)]
-> LHsBind GhcPs
mkRdrFunBindEC Arity
2 LHsExpr GhcPs -> LHsExpr GhcPs
forall a. a -> a
id GenLocated SrcSpan RdrName
fmap_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
fmap_eqns
    fmap_match_ctxt :: HsMatchContext GhcPs
fmap_match_ctxt = LIdP GhcPs -> HsMatchContext GhcPs
forall p. LIdP p -> HsMatchContext p
mkPrefixFunRhs GenLocated SrcSpan RdrName
LIdP GhcPs
fmap_name

    fmap_eqn :: DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
fmap_eqn DataCon
con = (State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
 -> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName]
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall a b c. (a -> b -> c) -> b -> a -> c
flip State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall s a. State s a -> s -> a
evalState [RdrName]
bs_RDRs (State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
 -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall a b. (a -> b) -> a -> b
$
                     HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> m (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con HsMatchContext GhcPs
fmap_match_ctxt [LPat GhcPs
f_Pat] DataCon
con [Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs))]
[LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)]
parts
      where
        parts :: [Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs))]
parts = FFoldType
  (Located (HsExpr GhcPs)
   -> State [RdrName] (Located (HsExpr GhcPs)))
-> DataCon
-> [Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs))]
forall a. FFoldType a -> DataCon -> [a]
foldDataConArgs FFoldType
  (Located (HsExpr GhcPs)
   -> State [RdrName] (Located (HsExpr GhcPs)))
FFoldType (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
ft_fmap DataCon
con

    fmap_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
fmap_eqns = (DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [DataCon] -> [Located (Match GhcPs (Located (HsExpr GhcPs)))]
forall a b. (a -> b) -> [a] -> [b]
map DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
fmap_eqn [DataCon]
data_cons

    ft_fmap :: FFoldType (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
    ft_fmap :: FFoldType (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
ft_fmap = FT :: forall a.
a
-> a
-> a
-> (a -> a -> a)
-> (TyCon -> [a] -> a)
-> (Type -> Type -> a -> a)
-> a
-> (TcTyVar -> a -> a)
-> FFoldType a
FT { ft_triv :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_triv = \Located (HsExpr GhcPs)
x -> Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Located (HsExpr GhcPs)
x
                   -- fmap f x = x
                 , ft_var :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_var  = \Located (HsExpr GhcPs)
x -> Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp LHsExpr GhcPs
f_Expr Located (HsExpr GhcPs)
LHsExpr GhcPs
x
                   -- fmap f x = f x
                 , ft_fun :: (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> (Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_fun  = \Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
h Located (HsExpr GhcPs)
x -> (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam ((LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
 -> State [RdrName] (LHsExpr GhcPs))
-> (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
forall a b. (a -> b) -> a -> b
$ \LHsExpr GhcPs
b -> do
                     Located (HsExpr GhcPs)
gg <- Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
LHsExpr GhcPs
b
                     Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
h (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp Located (HsExpr GhcPs)
LHsExpr GhcPs
x Located (HsExpr GhcPs)
LHsExpr GhcPs
gg
                   -- fmap f x = \b -> h (x (g b))
                 , ft_tup :: TyCon
-> [Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs))]
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_tup = ([LPat GhcPs]
 -> DataCon
 -> [Located (HsExpr GhcPs)
     -> State [RdrName] (Located (HsExpr GhcPs))]
 -> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon
-> [Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs))]
-> LHsExpr GhcPs
-> State [RdrName] (LHsExpr GhcPs)
forall (m :: * -> *) a.
Monad m =>
([LPat GhcPs]
 -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase (HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> m (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con HsMatchContext GhcPs
forall p. HsMatchContext p
CaseAlt)
                   -- fmap f x = case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
                 , ft_ty_app :: Type
-> Type
-> (Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_ty_app = \Type
_ Type
arg_ty Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
x ->
                     -- If the argument type is a bare occurrence of the
                     -- data type's last type variable, then we can generate
                     -- more efficient code.
                     -- See Note [Avoid unnecessary eta expansion in derived fmap implementations]
                     if Type -> Bool
tcIsTyVarTy Type
arg_ty
                       then Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
fmap_RDR [LHsExpr GhcPs
f_Expr,Located (HsExpr GhcPs)
LHsExpr GhcPs
x]
                       else do Located (HsExpr GhcPs)
gg <- (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)
g
                               Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
fmap_RDR [Located (HsExpr GhcPs)
LHsExpr GhcPs
gg,Located (HsExpr GhcPs)
LHsExpr GhcPs
x]
                   -- fmap f x = fmap g x
                 , ft_forall :: TcTyVar
-> (Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_forall = \TcTyVar
_ Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
x -> Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
x
                 , ft_bad_app :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_bad_app = String
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a. String -> a
panic String
"in other argument in ft_fmap"
                 , ft_co_var :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_co_var = String
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a. String -> a
panic String
"contravariant in ft_fmap" }

    -- See Note [Deriving <$]
    replace_name :: GenLocated SrcSpan RdrName
replace_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
replace_RDR

    -- See Note [EmptyDataDecls with Functor, Foldable, and Traversable]
    replace_bind :: LHsBind GhcPs
replace_bind = Arity
-> (LHsExpr GhcPs -> LHsExpr GhcPs)
-> GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)]
-> LHsBind GhcPs
mkRdrFunBindEC Arity
2 LHsExpr GhcPs -> LHsExpr GhcPs
forall a. a -> a
id GenLocated SrcSpan RdrName
replace_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
replace_eqns
    replace_match_ctxt :: HsMatchContext GhcPs
replace_match_ctxt = LIdP GhcPs -> HsMatchContext GhcPs
forall p. LIdP p -> HsMatchContext p
mkPrefixFunRhs GenLocated SrcSpan RdrName
LIdP GhcPs
replace_name

    replace_eqn :: DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
replace_eqn DataCon
con = (State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
 -> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName]
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall a b c. (a -> b -> c) -> b -> a -> c
flip State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall s a. State s a -> s -> a
evalState [RdrName]
bs_RDRs (State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
 -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall a b. (a -> b) -> a -> b
$
        HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> m (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con HsMatchContext GhcPs
replace_match_ctxt [LPat GhcPs
z_Pat] DataCon
con [Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs))]
[LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)]
parts
      where
        parts :: [Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs))]
parts = FFoldType
  (Located (HsExpr GhcPs)
   -> State [RdrName] (Located (HsExpr GhcPs)))
-> DataCon
-> [Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs))]
forall a. FFoldType a -> DataCon -> [a]
foldDataConArgs FFoldType
  (Located (HsExpr GhcPs)
   -> State [RdrName] (Located (HsExpr GhcPs)))
FFoldType (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
ft_replace DataCon
con

    replace_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
replace_eqns = (DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [DataCon] -> [Located (Match GhcPs (Located (HsExpr GhcPs)))]
forall a b. (a -> b) -> [a] -> [b]
map DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
replace_eqn [DataCon]
data_cons

    ft_replace :: FFoldType (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
    ft_replace :: FFoldType (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
ft_replace = FT :: forall a.
a
-> a
-> a
-> (a -> a -> a)
-> (TyCon -> [a] -> a)
-> (Type -> Type -> a -> a)
-> a
-> (TcTyVar -> a -> a)
-> FFoldType a
FT { ft_triv :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_triv = \Located (HsExpr GhcPs)
x -> Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Located (HsExpr GhcPs)
x
                   -- p <$ x = x
                 , ft_var :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_var  = \Located (HsExpr GhcPs)
_ -> Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Located (HsExpr GhcPs)
LHsExpr GhcPs
z_Expr
                   -- p <$ _ = p
                 , ft_fun :: (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> (Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_fun  = \Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
h Located (HsExpr GhcPs)
x -> (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam ((LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
 -> State [RdrName] (LHsExpr GhcPs))
-> (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
forall a b. (a -> b) -> a -> b
$ \LHsExpr GhcPs
b -> do
                     Located (HsExpr GhcPs)
gg <- Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
LHsExpr GhcPs
b
                     Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
h (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp Located (HsExpr GhcPs)
LHsExpr GhcPs
x Located (HsExpr GhcPs)
LHsExpr GhcPs
gg
                   -- p <$ x = \b -> h (x (g b))
                 , ft_tup :: TyCon
-> [Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs))]
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_tup = ([LPat GhcPs]
 -> DataCon
 -> [Located (HsExpr GhcPs)
     -> State [RdrName] (Located (HsExpr GhcPs))]
 -> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon
-> [Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs))]
-> LHsExpr GhcPs
-> State [RdrName] (LHsExpr GhcPs)
forall (m :: * -> *) a.
Monad m =>
([LPat GhcPs]
 -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase (HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> m (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con HsMatchContext GhcPs
forall p. HsMatchContext p
CaseAlt)
                   -- p <$ x = case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
                 , ft_ty_app :: Type
-> Type
-> (Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_ty_app = \Type
_ Type
arg_ty Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
x ->
                       -- If the argument type is a bare occurrence of the
                       -- data type's last type variable, then we can generate
                       -- more efficient code.
                       -- See [Deriving <$]
                       if Type -> Bool
tcIsTyVarTy Type
arg_ty
                         then Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
replace_RDR [LHsExpr GhcPs
z_Expr,Located (HsExpr GhcPs)
LHsExpr GhcPs
x]
                         else do Located (HsExpr GhcPs)
gg <- (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)
g
                                 Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
fmap_RDR [Located (HsExpr GhcPs)
LHsExpr GhcPs
gg,Located (HsExpr GhcPs)
LHsExpr GhcPs
x]
                   -- p <$ x = fmap (p <$) x
                 , ft_forall :: TcTyVar
-> (Located (HsExpr GhcPs)
    -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
ft_forall = \TcTyVar
_ Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
x -> Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
g Located (HsExpr GhcPs)
x
                 , ft_bad_app :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_bad_app = String
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a. String -> a
panic String
"in other argument in ft_replace"
                 , ft_co_var :: Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
ft_co_var = String
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a. String -> a
panic String
"contravariant in ft_replace" }

    -- Con a1 a2 ... -> Con (f1 a1) (f2 a2) ...
    match_for_con :: Monad m
                  => HsMatchContext GhcPs
                  -> [LPat GhcPs] -> DataCon
                  -> [LHsExpr GhcPs -> m (LHsExpr GhcPs)]
                  -> m (LMatch GhcPs (LHsExpr GhcPs))
    match_for_con :: HsMatchContext GhcPs
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> m (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con HsMatchContext GhcPs
ctxt = HsMatchContext GhcPs
-> (RdrName -> [m (Located (HsExpr GhcPs))] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> m (Located (HsExpr GhcPs))]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *) a.
Monad m =>
HsMatchContext GhcPs
-> (RdrName -> [a] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> a]
-> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch HsMatchContext GhcPs
ctxt ((RdrName -> [m (Located (HsExpr GhcPs))] -> m (LHsExpr GhcPs))
 -> [LPat GhcPs]
 -> DataCon
 -> [LHsExpr GhcPs -> m (Located (HsExpr GhcPs))]
 -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> (RdrName -> [m (Located (HsExpr GhcPs))] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> m (Located (HsExpr GhcPs))]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$
        \RdrName
con_name [m (Located (HsExpr GhcPs))]
xsM -> do [Located (HsExpr GhcPs)]
xs <- [m (Located (HsExpr GhcPs))] -> m [Located (HsExpr GhcPs)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [m (Located (HsExpr GhcPs))]
xsM
                            Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
con_name [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
xs  -- Con x1 x2 ..

{-
Note [Avoid unnecessary eta expansion in derived fmap implementations]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For the sake of simplicity, the algorithm that derived implementations of
fmap used to have a single case that dealt with applications of some type
constructor T (where T is not a tuple type constructor):

  $(fmap 'a '(T b1 b2) x) = fmap (\y. $(fmap 'a 'b2 y)) x -- when a only occurs in the last parameter, b2

This generated less than optimal code in certain situations, however. Consider
this example:

  data List a = Nil | Cons a (List a) deriving Functor

This would generate the following Functor instance:

  instance Functor List where
    fmap f Nil = Nil
    fmap f (Cons x xs) = Cons (f x) (fmap (\y -> f y) xs)

The code `fmap (\y -> f y) xs` is peculiar, since it eta expands an application
of `f`. What's worse, this eta expansion actually degrades performance! To see
why, we can trace an invocation of fmap on a small List:

  fmap id     $ Cons 0 $ Cons 0 $ Cons 0 $ Cons 0 Nil

  Cons (id 0) $ fmap (\y -> id y)
              $ Cons 0 $ Cons 0 $ Cons 0 Nil

  Cons (id 0) $ Cons ((\y -> id y) 0)
              $ fmap (\y' -> (\y -> id y) y')
              $ Cons 0 $ Cons 0 Nil

  Cons (id 0) $ Cons ((\y -> id y) 0)
              $ Cons ((\y' -> (\y -> id y) y') 0)
              $ fmap (\y'' -> (\y' -> (\y -> id y) y') y'')
              $ Cons 0 Nil

  Cons (id 0) $ Cons ((\y -> id y) 0)
              $ Cons ((\y' -> (\y -> id y) y') 0)
              $ Cons ((\y'' -> (\y' -> (\y -> id y) y') y'') 0)
              $ fmap (\y''' -> (\y'' -> (\y' -> (\y -> id y) y') y'') y''')
              $ Nil

  Cons (id 0) $ Cons ((\y -> id y) 0)
              $ Cons ((\y' -> (\y -> id y) y') 0)
              $ Cons ((\y'' -> (\y' -> (\y -> id y) y') y'') 0)
              $ Nil

Notice how the number of lambdas—and hence, the number of closures—one
needs to evaluate grows very quickly. In general, a List with N cons cells will
require (1 + 2 + ... (N-1)) beta reductions, which takes O(N^2) time! This is
what caused the performance issues observed in #7436.

But hold on a second: shouldn't GHC's optimizer be able to eta reduce
`\y -> f y` to `f` and avoid these beta reductions? Unfortunately, this is not
the case. In general, eta reduction can change the semantics of a program. For
instance, (\x -> ⊥) `seq` () converges, but ⊥ `seq` () diverges. It just so
happens that the fmap implementation above would have the same semantics
regardless of whether or not `\y -> f y` or `f` is used, but GHC's optimizer is
not yet smart enough to realize this (see #17881).

To avoid this quadratic blowup, we add a special case to $fmap that applies
`fmap f` directly:

  $(fmap 'a '(T b1 a) x)  = fmap f x -- when a only occurs directly as the last argument of T
  $(fmap 'a '(T b1 b2) x) = fmap (\y. $(fmap 'a 'b2 y)) x -- when a only occurs in the last parameter, b2

With this modified algorithm, the derived Functor List instance becomes:

  instance Functor List where
    fmap f Nil = Nil
    fmap f (Cons x xs) = Cons (f x) (fmap f xs)

No lambdas in sight, just the way we like it.

This special case does not prevent all sources quadratic closure buildup,
however. In this example:

  data PolyList a = PLNil | PLCons a (PolyList (PolyList a))
    deriving Functor

We would derive the following code:

  instance Functor PolyList where
    fmap f PLNil = PLNil
    fmap f (PLCons x xs) = PLCons (f x) (fmap (\y -> fmap f y) xs)

The use of `fmap (\y -> fmap f y) xs` builds up closures in much the same way
as `fmap (\y -> f y) xs`. The difference here is that even if we eta reduced
to `fmap (fmap f) xs`, GHC would /still/ build up a closure, since we are
recursively invoking fmap with a different argument (fmap f). Since we end up
paying the price of building a closure either way, we do not extend the special
case in $fmap any further, since it wouldn't buy us anything.

The ft_ty_app field of FFoldType distinguishes between these two $fmap cases by
inspecting the argument type. If the argument type is a bare type variable,
then we can conclude the type variable /must/ be the same as the data type's
last type parameter. We know that this must be the case since there is an
invariant that the argument type in ft_ty_app will always contain the last
type parameter somewhere (see Note [FFoldType and functorLikeTraverse]), so
if the argument type is a bare variable, then that must be exactly the last
type parameter.

Note that the ft_ty_app case of ft_replace (which derives implementations of
(<$)) also inspects the argument type to generate more efficient code.
See Note [Deriving <$].

Note [Deriving <$]
~~~~~~~~~~~~~~~~~~

We derive the definition of <$. Allowing this to take the default definition
can lead to memory leaks: mapping over a structure with a constant function can
fill the result structure with trivial thunks that retain the values from the
original structure. The simplifier seems to handle this all right for simple
types, but not for recursive ones. Consider

data Tree a = Bin !(Tree a) a !(Tree a) | Tip deriving Functor

-- fmap _ Tip = Tip
-- fmap f (Bin l v r) = Bin (fmap f l) (f v) (fmap f r)

Using the default definition of <$, we get (<$) x = fmap (\_ -> x) and that
simplifies no further. Why is that? `fmap` is defined recursively, so GHC
cannot inline it. The static argument transformation would turn the definition
into a non-recursive one

-- fmap f = go where
--   go Tip = Tip
--   go (Bin l v r) = Bin (go l) (f v) (go r)

which GHC could inline, producing an efficient definion of `<$`. But there are
several problems. First, GHC does not perform the static argument transformation
by default, even with -O2. Second, even when it does perform the static argument
transformation, it does so only when there are at least two static arguments,
which is not the case for fmap. Finally, when the type in question is
non-regular, such as

data Nesty a = Z a | S (Nesty a) (Nest (a, a))

the function argument is no longer (entirely) static, so the static argument
transformation will do nothing for us.

Applying the default definition of `<$` will produce a tree full of thunks that
look like ((\_ -> x) x0), which represents unnecessary thunk allocation and
also retention of the previous value, potentially leaking memory. Instead, we
derive <$ separately. Two aspects are different from fmap: the case of the
sought type variable (ft_var) and the case of a type application (ft_ty_app).
The interesting one is ft_ty_app. We have to distinguish two cases: the
"immediate" case where the type argument *is* the sought type variable, and
the "nested" case where the type argument *contains* the sought type variable.

The immediate case:

Suppose we have

data Imm a = Imm (F ... a)

Then we want to define

x <$ Imm q = Imm (x <$ q)

The nested case:

Suppose we have

data Nes a = Nes (F ... (G a))

Then we want to define

x <$ Nes q = Nes (fmap (x <$) q)

We inspect the argument type in ft_ty_app
(see Note [FFoldType and functorLikeTraverse]) to distinguish between these
two cases. If the argument type is a bare type variable, then we know that it
must be the same variable as the data type's last type parameter.
This is very similar to a trick that derived fmap implementations
use in their own ft_ty_app case.
See Note [Avoid unnecessary eta expansion in derived fmap implementations],
which explains why checking if the argument type is a bare variable is
the right thing to do.

We could, but do not, give tuples special treatment to improve efficiency
in some cases. Suppose we have

data Nest a = Z a | S (Nest (a,a))

The optimal definition would be

x <$ Z _ = Z x
x <$ S t = S ((x, x) <$ t)

which produces a result with maximal internal sharing. The reason we do not
attempt to treat this case specially is that we have no way to give
user-provided tuple-like types similar treatment. If the user changed the
definition to

data Pair a = Pair a a
data Nest a = Z a | S (Nest (Pair a))

they would experience a surprising degradation in performance. -}


{-
Utility functions related to Functor deriving.

Since several things use the same pattern of traversal, this is abstracted into functorLikeTraverse.
This function works like a fold: it makes a value of type 'a' in a bottom up way.
-}

-- Generic traversal for Functor deriving
-- See Note [FFoldType and functorLikeTraverse]
data FFoldType a      -- Describes how to fold over a Type in a functor like way
   = FT { FFoldType a -> a
ft_triv    :: a
          -- ^ Does not contain variable
        , FFoldType a -> a
ft_var     :: a
          -- ^ The variable itself
        , FFoldType a -> a
ft_co_var  :: a
          -- ^ The variable itself, contravariantly
        , FFoldType a -> a -> a -> a
ft_fun     :: a -> a -> a
          -- ^ Function type
        , FFoldType a -> TyCon -> [a] -> a
ft_tup     :: TyCon -> [a] -> a
          -- ^ Tuple type. The @[a]@ is the result of folding over the
          --   arguments of the tuple.
        , FFoldType a -> Type -> Type -> a -> a
ft_ty_app  :: Type -> Type -> a -> a
          -- ^ Type app, variable only in last argument. The two 'Type's are
          --   the function and argument parts of @fun_ty arg_ty@,
          --   respectively.
        , FFoldType a -> a
ft_bad_app :: a
          -- ^ Type app, variable other than in last argument
        , FFoldType a -> TcTyVar -> a -> a
ft_forall  :: TcTyVar -> a -> a
          -- ^ Forall type
     }

functorLikeTraverse :: forall a.
                       TyVar         -- ^ Variable to look for
                    -> FFoldType a   -- ^ How to fold
                    -> Type          -- ^ Type to process
                    -> a
functorLikeTraverse :: TcTyVar -> FFoldType a -> Type -> a
functorLikeTraverse TcTyVar
var (FT { ft_triv :: forall a. FFoldType a -> a
ft_triv = a
caseTrivial,     ft_var :: forall a. FFoldType a -> a
ft_var = a
caseVar
                            , ft_co_var :: forall a. FFoldType a -> a
ft_co_var = a
caseCoVar,     ft_fun :: forall a. FFoldType a -> a -> a -> a
ft_fun = a -> a -> a
caseFun
                            , ft_tup :: forall a. FFoldType a -> TyCon -> [a] -> a
ft_tup = TyCon -> [a] -> a
caseTuple,        ft_ty_app :: forall a. FFoldType a -> Type -> Type -> a -> a
ft_ty_app = Type -> Type -> a -> a
caseTyApp
                            , ft_bad_app :: forall a. FFoldType a -> a
ft_bad_app = a
caseWrongArg, ft_forall :: forall a. FFoldType a -> TcTyVar -> a -> a
ft_forall = TcTyVar -> a -> a
caseForAll })
                    Type
ty
  = (a, Bool) -> a
forall a b. (a, b) -> a
fst (Bool -> Type -> (a, Bool)
go Bool
False Type
ty)
  where
    go :: Bool        -- Covariant or contravariant context
       -> Type
       -> (a, Bool)   -- (result of type a, does type contain var)

    go :: Bool -> Type -> (a, Bool)
go Bool
co Type
ty | Just Type
ty' <- Type -> Maybe Type
tcView Type
ty = Bool -> Type -> (a, Bool)
go Bool
co Type
ty'
    go Bool
co (TyVarTy    TcTyVar
v) | TcTyVar
v TcTyVar -> TcTyVar -> Bool
forall a. Eq a => a -> a -> Bool
== TcTyVar
var = (if Bool
co then a
caseCoVar else a
caseVar,Bool
True)
    go Bool
co (FunTy { ft_arg :: Type -> Type
ft_arg = Type
x, ft_res :: Type -> Type
ft_res = Type
y, ft_af :: Type -> AnonArgFlag
ft_af = AnonArgFlag
af })
       | AnonArgFlag
InvisArg <- AnonArgFlag
af = Bool -> Type -> (a, Bool)
go Bool
co Type
y
       | Bool
xc Bool -> Bool -> Bool
|| Bool
yc       = (a -> a -> a
caseFun a
xr a
yr,Bool
True)
       where (a
xr,Bool
xc) = Bool -> Type -> (a, Bool)
go (Bool -> Bool
not Bool
co) Type
x
             (a
yr,Bool
yc) = Bool -> Type -> (a, Bool)
go Bool
co       Type
y
    go Bool
co (AppTy    Type
x Type
y) | Bool
xc = (a
caseWrongArg,   Bool
True)
                         | Bool
yc = (Type -> Type -> a -> a
caseTyApp Type
x Type
y a
yr, Bool
True)
        where (a
_, Bool
xc) = Bool -> Type -> (a, Bool)
go Bool
co Type
x
              (a
yr,Bool
yc) = Bool -> Type -> (a, Bool)
go Bool
co Type
y
    go Bool
co ty :: Type
ty@(TyConApp TyCon
con [Type]
args)
       | Bool -> Bool
not ([Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or [Bool]
xcs)     = (a
caseTrivial, Bool
False)   -- Variable does not occur
       -- At this point we know that xrs, xcs is not empty,
       -- and at least one xr is True
       | TyCon -> Bool
isTupleTyCon TyCon
con = (TyCon -> [a] -> a
caseTuple TyCon
con [a]
xrs, Bool
True)
       | [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> [Bool]
forall a. [a] -> [a]
init [Bool]
xcs)    = (a
caseWrongArg, Bool
True)         -- T (..var..)    ty
       | Just (Type
fun_ty, Type
arg_ty) <- Type -> Maybe (Type, Type)
splitAppTy_maybe Type
ty    -- T (..no var..) ty
                          = (Type -> Type -> a -> a
caseTyApp Type
fun_ty Type
arg_ty ([a] -> a
forall a. [a] -> a
last [a]
xrs), Bool
True)
       | Bool
otherwise        = (a
caseWrongArg, Bool
True)   -- Non-decomposable (eg type function)
       where
         -- When folding over an unboxed tuple, we must explicitly drop the
         -- runtime rep arguments, or else GHC will generate twice as many
         -- variables in a unboxed tuple pattern match and expression as it
         -- actually needs. See #12399
         ([a]
xrs,[Bool]
xcs) = [(a, Bool)] -> ([a], [Bool])
forall a b. [(a, b)] -> ([a], [b])
unzip ((Type -> (a, Bool)) -> [Type] -> [(a, Bool)]
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> Type -> (a, Bool)
go Bool
co) ([Type] -> [Type]
dropRuntimeRepArgs [Type]
args))
    go Bool
co (ForAllTy (Bndr TcTyVar
v ArgFlag
vis) Type
x)
       | ArgFlag -> Bool
isVisibleArgFlag ArgFlag
vis = String -> (a, Bool)
forall a. String -> a
panic String
"unexpected visible binder"
       | TcTyVar
v TcTyVar -> TcTyVar -> Bool
forall a. Eq a => a -> a -> Bool
/= TcTyVar
var Bool -> Bool -> Bool
&& Bool
xc       = (TcTyVar -> a -> a
caseForAll TcTyVar
v a
xr,Bool
True)
       where (a
xr,Bool
xc) = Bool -> Type -> (a, Bool)
go Bool
co Type
x

    go Bool
_ Type
_ = (a
caseTrivial,Bool
False)

-- Return all syntactic subterms of ty that contain var somewhere
-- These are the things that should appear in instance constraints
deepSubtypesContaining :: TyVar -> Type -> [TcType]
deepSubtypesContaining :: TcTyVar -> Type -> [Type]
deepSubtypesContaining TcTyVar
tv
  = TcTyVar -> FFoldType [Type] -> Type -> [Type]
forall a. TcTyVar -> FFoldType a -> Type -> a
functorLikeTraverse TcTyVar
tv
        (FT :: forall a.
a
-> a
-> a
-> (a -> a -> a)
-> (TyCon -> [a] -> a)
-> (Type -> Type -> a -> a)
-> a
-> (TcTyVar -> a -> a)
-> FFoldType a
FT { ft_triv :: [Type]
ft_triv = []
            , ft_var :: [Type]
ft_var = []
            , ft_fun :: [Type] -> [Type] -> [Type]
ft_fun = [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
(++)
            , ft_tup :: TyCon -> [[Type]] -> [Type]
ft_tup = \TyCon
_ [[Type]]
xs -> [[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Type]]
xs
            , ft_ty_app :: Type -> Type -> [Type] -> [Type]
ft_ty_app = \Type
t Type
_ [Type]
ts -> Type
tType -> [Type] -> [Type]
forall a. a -> [a] -> [a]
:[Type]
ts
            , ft_bad_app :: [Type]
ft_bad_app = String -> [Type]
forall a. String -> a
panic String
"in other argument in deepSubtypesContaining"
            , ft_co_var :: [Type]
ft_co_var = String -> [Type]
forall a. String -> a
panic String
"contravariant in deepSubtypesContaining"
            , ft_forall :: TcTyVar -> [Type] -> [Type]
ft_forall = \TcTyVar
v [Type]
xs -> (Type -> Bool) -> [Type] -> [Type]
forall a. (a -> Bool) -> [a] -> [a]
filterOut ((TcTyVar
v TcTyVar -> VarSet -> Bool
`elemVarSet`) (VarSet -> Bool) -> (Type -> VarSet) -> Type -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> VarSet
tyCoVarsOfType) [Type]
xs })


foldDataConArgs :: FFoldType a -> DataCon -> [a]
-- Fold over the arguments of the datacon
foldDataConArgs :: FFoldType a -> DataCon -> [a]
foldDataConArgs FFoldType a
ft DataCon
con
  = (Type -> a) -> [Type] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Type -> a
foldArg ((Scaled Type -> Type) -> [Scaled Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Scaled Type -> Type
forall a. Scaled a -> a
scaledThing ([Scaled Type] -> [Type]) -> [Scaled Type] -> [Type]
forall a b. (a -> b) -> a -> b
$ DataCon -> [Scaled Type]
dataConOrigArgTys DataCon
con)
  where
    foldArg :: Type -> a
foldArg
      = case Type -> Maybe TcTyVar
getTyVar_maybe ([Type] -> Type
forall a. [a] -> a
last (Type -> [Type]
tyConAppArgs (DataCon -> Type
dataConOrigResTy DataCon
con))) of
             Just TcTyVar
tv -> TcTyVar -> FFoldType a -> Type -> a
forall a. TcTyVar -> FFoldType a -> Type -> a
functorLikeTraverse TcTyVar
tv FFoldType a
ft
             Maybe TcTyVar
Nothing -> a -> Type -> a
forall a b. a -> b -> a
const (FFoldType a -> a
forall a. FFoldType a -> a
ft_triv FFoldType a
ft)
    -- If we are deriving Foldable for a GADT, there is a chance that the last
    -- type variable in the data type isn't actually a type variable at all.
    -- (for example, this can happen if the last type variable is refined to
    -- be a concrete type such as Int). If the last type variable is refined
    -- to be a specific type, then getTyVar_maybe will return Nothing.
    -- See Note [DeriveFoldable with ExistentialQuantification]
    --
    -- The kind checks have ensured the last type parameter is of kind *.

-- Make a HsLam using a fresh variable from a State monad
mkSimpleLam :: (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
            -> State [RdrName] (LHsExpr GhcPs)
-- (mkSimpleLam fn) returns (\x. fn(x))
mkSimpleLam :: (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)
lam =
    State [RdrName] [RdrName]
forall s. State s s
get State [RdrName] [RdrName]
-> ([RdrName] -> State [RdrName] (Located (HsExpr GhcPs)))
-> State [RdrName] (Located (HsExpr GhcPs))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      RdrName
n:[RdrName]
names -> do
        [RdrName] -> State [RdrName] ()
forall s. s -> State s ()
put [RdrName]
names
        Located (HsExpr GhcPs)
body <- LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)
lam (IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
n)
        Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return ([LPat GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (p :: Pass).
(IsPass p, XMG (GhcPass p) (LHsExpr (GhcPass p)) ~ NoExtField) =>
[LPat (GhcPass p)] -> LHsExpr (GhcPass p) -> LHsExpr (GhcPass p)
mkHsLam [IdP GhcPs -> LPat GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LPat (GhcPass id)
nlVarPat RdrName
IdP GhcPs
n] Located (HsExpr GhcPs)
LHsExpr GhcPs
body)
      [RdrName]
_ -> String -> State [RdrName] (Located (HsExpr GhcPs))
forall a. String -> a
panic String
"mkSimpleLam"

mkSimpleLam2 :: (LHsExpr GhcPs -> LHsExpr GhcPs
             -> State [RdrName] (LHsExpr GhcPs))
             -> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam2 :: (LHsExpr GhcPs -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam2 LHsExpr GhcPs -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)
lam =
    State [RdrName] [RdrName]
forall s. State s s
get State [RdrName] [RdrName]
-> ([RdrName] -> State [RdrName] (Located (HsExpr GhcPs)))
-> State [RdrName] (Located (HsExpr GhcPs))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      RdrName
n1:RdrName
n2:[RdrName]
names -> do
        [RdrName] -> State [RdrName] ()
forall s. s -> State s ()
put [RdrName]
names
        Located (HsExpr GhcPs)
body <- LHsExpr GhcPs -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs)
lam (IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
n1) (IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
n2)
        Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return ([LPat GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (p :: Pass).
(IsPass p, XMG (GhcPass p) (LHsExpr (GhcPass p)) ~ NoExtField) =>
[LPat (GhcPass p)] -> LHsExpr (GhcPass p) -> LHsExpr (GhcPass p)
mkHsLam [IdP GhcPs -> LPat GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LPat (GhcPass id)
nlVarPat RdrName
IdP GhcPs
n1,IdP GhcPs -> LPat GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LPat (GhcPass id)
nlVarPat RdrName
IdP GhcPs
n2] Located (HsExpr GhcPs)
LHsExpr GhcPs
body)
      [RdrName]
_ -> String -> State [RdrName] (Located (HsExpr GhcPs))
forall a. String -> a
panic String
"mkSimpleLam2"

-- "Con a1 a2 a3 -> fold [x1 a1, x2 a2, x3 a3]"
--
-- @mkSimpleConMatch fold extra_pats con insides@ produces a match clause in
-- which the LHS pattern-matches on @extra_pats@, followed by a match on the
-- constructor @con@ and its arguments. The RHS folds (with @fold@) over @con@
-- and its arguments, applying an expression (from @insides@) to each of the
-- respective arguments of @con@.
mkSimpleConMatch :: Monad m => HsMatchContext GhcPs
                 -> (RdrName -> [a] -> m (LHsExpr GhcPs))
                 -> [LPat GhcPs]
                 -> DataCon
                 -> [LHsExpr GhcPs -> a]
                 -> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch :: HsMatchContext GhcPs
-> (RdrName -> [a] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [LHsExpr GhcPs -> a]
-> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch HsMatchContext GhcPs
ctxt RdrName -> [a] -> m (LHsExpr GhcPs)
fold [LPat GhcPs]
extra_pats DataCon
con [LHsExpr GhcPs -> a]
insides = do
    let con_name :: RdrName
con_name = DataCon -> RdrName
forall thing. NamedThing thing => thing -> RdrName
getRdrName DataCon
con
    let vars_needed :: [RdrName]
vars_needed = [Located (HsExpr GhcPs) -> a] -> [RdrName] -> [RdrName]
forall b a. [b] -> [a] -> [a]
takeList [Located (HsExpr GhcPs) -> a]
[LHsExpr GhcPs -> a]
insides [RdrName]
as_RDRs
    let bare_pat :: LPat GhcPs
bare_pat = RdrName -> [RdrName] -> LPat GhcPs
nlConVarPat RdrName
con_name [RdrName]
vars_needed
    let pat :: Located (Pat GhcPs)
pat = if [RdrName] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [RdrName]
vars_needed
          then Located (Pat GhcPs)
LPat GhcPs
bare_pat
          else LPat GhcPs -> LPat GhcPs
forall (name :: Pass). LPat (GhcPass name) -> LPat (GhcPass name)
nlParPat LPat GhcPs
bare_pat
    Located (HsExpr GhcPs)
rhs <- RdrName -> [a] -> m (LHsExpr GhcPs)
fold RdrName
con_name
                (((Located (HsExpr GhcPs) -> a) -> RdrName -> a)
-> [Located (HsExpr GhcPs) -> a] -> [RdrName] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Located (HsExpr GhcPs) -> a
i RdrName
v -> Located (HsExpr GhcPs) -> a
i (Located (HsExpr GhcPs) -> a) -> Located (HsExpr GhcPs) -> a
forall a b. (a -> b) -> a -> b
$ IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
v) [Located (HsExpr GhcPs) -> a]
[LHsExpr GhcPs -> a]
insides [RdrName]
vars_needed)
    Located (Match GhcPs (Located (HsExpr GhcPs)))
-> m (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (Match GhcPs (Located (HsExpr GhcPs)))
 -> m (Located (Match GhcPs (Located (HsExpr GhcPs)))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
-> m (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall a b. (a -> b) -> a -> b
$ HsMatchContext (NoGhcTc GhcPs)
-> [LPat GhcPs]
-> LHsExpr GhcPs
-> Located (HsLocalBinds GhcPs)
-> LMatch GhcPs (LHsExpr GhcPs)
forall (p :: Pass).
IsPass p =>
HsMatchContext (NoGhcTc (GhcPass p))
-> [LPat (GhcPass p)]
-> LHsExpr (GhcPass p)
-> Located (HsLocalBinds (GhcPass p))
-> LMatch (GhcPass p) (LHsExpr (GhcPass p))
mkMatch HsMatchContext GhcPs
HsMatchContext (NoGhcTc GhcPs)
ctxt ([Located (Pat GhcPs)]
[LPat GhcPs]
extra_pats [Located (Pat GhcPs)]
-> [Located (Pat GhcPs)] -> [Located (Pat GhcPs)]
forall a. [a] -> [a] -> [a]
++ [Located (Pat GhcPs)
pat]) Located (HsExpr GhcPs)
LHsExpr GhcPs
rhs
                     (HsLocalBinds GhcPs -> Located (HsLocalBinds GhcPs)
forall e. e -> Located e
noLoc HsLocalBinds GhcPs
forall (a :: Pass) (b :: Pass).
HsLocalBindsLR (GhcPass a) (GhcPass b)
emptyLocalBinds)

-- "Con a1 a2 a3 -> fmap (\b2 -> Con a1 b2 a3) (traverse f a2)"
--
-- @mkSimpleConMatch2 fold extra_pats con insides@ behaves very similarly to
-- 'mkSimpleConMatch', with two key differences:
--
-- 1. @insides@ is a @[Maybe (LHsExpr RdrName)]@ instead of a
--    @[LHsExpr RdrName]@. This is because it filters out the expressions
--    corresponding to arguments whose types do not mention the last type
--    variable in a derived 'Foldable' or 'Traversable' instance (i.e., the
--    'Nothing' elements of @insides@).
--
-- 2. @fold@ takes an expression as its first argument instead of a
--    constructor name. This is because it uses a specialized
--    constructor function expression that only takes as many parameters as
--    there are argument types that mention the last type variable.
--
-- See Note [Generated code for DeriveFoldable and DeriveTraversable]
mkSimpleConMatch2 :: Monad m
                  => HsMatchContext GhcPs
                  -> (LHsExpr GhcPs -> [LHsExpr GhcPs]
                                      -> m (LHsExpr GhcPs))
                  -> [LPat GhcPs]
                  -> DataCon
                  -> [Maybe (LHsExpr GhcPs)]
                  -> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch2 :: HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch2 HsMatchContext GhcPs
ctxt LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs)
fold [LPat GhcPs]
extra_pats DataCon
con [Maybe (LHsExpr GhcPs)]
insides = do
    let con_name :: RdrName
con_name = DataCon -> RdrName
forall thing. NamedThing thing => thing -> RdrName
getRdrName DataCon
con
        vars_needed :: [RdrName]
vars_needed = [Maybe (Located (HsExpr GhcPs))] -> [RdrName] -> [RdrName]
forall b a. [b] -> [a] -> [a]
takeList [Maybe (Located (HsExpr GhcPs))]
[Maybe (LHsExpr GhcPs)]
insides [RdrName]
as_RDRs
        pat :: LPat GhcPs
pat = RdrName -> [RdrName] -> LPat GhcPs
nlConVarPat RdrName
con_name [RdrName]
vars_needed
        -- Make sure to zip BEFORE invoking catMaybes. We want the variable
        -- indices in each expression to match up with the argument indices
        -- in con_expr (defined below).
        exps :: [Located (HsExpr GhcPs)]
exps = [Maybe (Located (HsExpr GhcPs))] -> [Located (HsExpr GhcPs)]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (Located (HsExpr GhcPs))] -> [Located (HsExpr GhcPs)])
-> [Maybe (Located (HsExpr GhcPs))] -> [Located (HsExpr GhcPs)]
forall a b. (a -> b) -> a -> b
$ (Maybe (Located (HsExpr GhcPs))
 -> RdrName -> Maybe (Located (HsExpr GhcPs)))
-> [Maybe (Located (HsExpr GhcPs))]
-> [RdrName]
-> [Maybe (Located (HsExpr GhcPs))]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Maybe (Located (HsExpr GhcPs))
i RdrName
v -> (LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
`nlHsApp` IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
v) (Located (HsExpr GhcPs) -> Located (HsExpr GhcPs))
-> Maybe (Located (HsExpr GhcPs)) -> Maybe (Located (HsExpr GhcPs))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (Located (HsExpr GhcPs))
i)
                                   [Maybe (Located (HsExpr GhcPs))]
[Maybe (LHsExpr GhcPs)]
insides [RdrName]
vars_needed
        -- An element of argTysTyVarInfo is True if the constructor argument
        -- with the same index has a type which mentions the last type
        -- variable.
        argTysTyVarInfo :: [Bool]
argTysTyVarInfo = (Maybe (Located (HsExpr GhcPs)) -> Bool)
-> [Maybe (Located (HsExpr GhcPs))] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map Maybe (Located (HsExpr GhcPs)) -> Bool
forall a. Maybe a -> Bool
isJust [Maybe (Located (HsExpr GhcPs))]
[Maybe (LHsExpr GhcPs)]
insides
        ([Located (HsExpr GhcPs)]
asWithTyVar, [Located (HsExpr GhcPs)]
asWithoutTyVar) = [Bool]
-> [Located (HsExpr GhcPs)]
-> ([Located (HsExpr GhcPs)], [Located (HsExpr GhcPs)])
forall a. [Bool] -> [a] -> ([a], [a])
partitionByList [Bool]
argTysTyVarInfo [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
as_Vars

        con_expr :: Located (HsExpr GhcPs)
con_expr
          | [Located (HsExpr GhcPs)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Located (HsExpr GhcPs)]
asWithTyVar = IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
con_name [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
asWithoutTyVar
          | Bool
otherwise =
              let bs :: [RdrName]
bs   = [Bool] -> [RdrName] -> [RdrName]
forall a. [Bool] -> [a] -> [a]
filterByList  [Bool]
argTysTyVarInfo [RdrName]
bs_RDRs
                  vars :: [Located (HsExpr GhcPs)]
vars = [Bool]
-> [Located (HsExpr GhcPs)]
-> [Located (HsExpr GhcPs)]
-> [Located (HsExpr GhcPs)]
forall a. [Bool] -> [a] -> [a] -> [a]
filterByLists [Bool]
argTysTyVarInfo [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
bs_Vars [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
as_Vars
              in [LPat GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (p :: Pass).
(IsPass p, XMG (GhcPass p) (LHsExpr (GhcPass p)) ~ NoExtField) =>
[LPat (GhcPass p)] -> LHsExpr (GhcPass p) -> LHsExpr (GhcPass p)
mkHsLam ((RdrName -> Located (Pat GhcPs))
-> [RdrName] -> [Located (Pat GhcPs)]
forall a b. (a -> b) -> [a] -> [b]
map RdrName -> Located (Pat GhcPs)
forall (id :: Pass). IdP (GhcPass id) -> LPat (GhcPass id)
nlVarPat [RdrName]
bs) (IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
con_name [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
vars)

    Located (HsExpr GhcPs)
rhs <- LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs)
fold Located (HsExpr GhcPs)
LHsExpr GhcPs
con_expr [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
exps
    Located (Match GhcPs (Located (HsExpr GhcPs)))
-> m (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (Match GhcPs (Located (HsExpr GhcPs)))
 -> m (Located (Match GhcPs (Located (HsExpr GhcPs)))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
-> m (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall a b. (a -> b) -> a -> b
$ HsMatchContext (NoGhcTc GhcPs)
-> [LPat GhcPs]
-> LHsExpr GhcPs
-> Located (HsLocalBinds GhcPs)
-> LMatch GhcPs (LHsExpr GhcPs)
forall (p :: Pass).
IsPass p =>
HsMatchContext (NoGhcTc (GhcPass p))
-> [LPat (GhcPass p)]
-> LHsExpr (GhcPass p)
-> Located (HsLocalBinds (GhcPass p))
-> LMatch (GhcPass p) (LHsExpr (GhcPass p))
mkMatch HsMatchContext GhcPs
HsMatchContext (NoGhcTc GhcPs)
ctxt ([Located (Pat GhcPs)]
[LPat GhcPs]
extra_pats [Located (Pat GhcPs)]
-> [Located (Pat GhcPs)] -> [Located (Pat GhcPs)]
forall a. [a] -> [a] -> [a]
++ [Located (Pat GhcPs)
LPat GhcPs
pat]) Located (HsExpr GhcPs)
LHsExpr GhcPs
rhs
                     (HsLocalBinds GhcPs -> Located (HsLocalBinds GhcPs)
forall e. e -> Located e
noLoc HsLocalBinds GhcPs
forall (a :: Pass) (b :: Pass).
HsLocalBindsLR (GhcPass a) (GhcPass b)
emptyLocalBinds)

-- "case x of (a1,a2,a3) -> fold [x1 a1, x2 a2, x3 a3]"
mkSimpleTupleCase :: Monad m => ([LPat GhcPs] -> DataCon -> [a]
                                 -> m (LMatch GhcPs (LHsExpr GhcPs)))
                  -> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase :: ([LPat GhcPs]
 -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase [LPat GhcPs] -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con TyCon
tc [a]
insides LHsExpr GhcPs
x
  = do { let data_con :: DataCon
data_con = TyCon -> DataCon
tyConSingleDataCon TyCon
tc
       ; Located (Match GhcPs (Located (HsExpr GhcPs)))
match <- [LPat GhcPs] -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con [] DataCon
data_con [a]
insides
       ; Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ LHsExpr GhcPs -> [LMatch GhcPs (LHsExpr GhcPs)] -> LHsExpr GhcPs
nlHsCase LHsExpr GhcPs
x [Located (Match GhcPs (Located (HsExpr GhcPs)))
LMatch GhcPs (LHsExpr GhcPs)
match] }

{-
************************************************************************
*                                                                      *
                        Foldable instances

 see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html

*                                                                      *
************************************************************************

Deriving Foldable instances works the same way as Functor instances,
only Foldable instances are not possible for function types at all.
Given (data T a = T a a (T a) deriving Foldable), we get:

  instance Foldable T where
      foldr f z (T x1 x2 x3) =
        $(foldr 'a 'a) x1 ( $(foldr 'a 'a) x2 ( $(foldr 'a '(T a)) x3 z ) )

-XDeriveFoldable is different from -XDeriveFunctor in that it filters out
arguments to the constructor that would produce useless code in a Foldable
instance. For example, the following datatype:

  data Foo a = Foo Int a Int deriving Foldable

would have the following generated Foldable instance:

  instance Foldable Foo where
    foldr f z (Foo x1 x2 x3) = $(foldr 'a 'a) x2

since neither of the two Int arguments are folded over.

The cases are:

  $(foldr 'a 'a)         =  f
  $(foldr 'a '(b1,b2))   =  \x z -> case x of (x1,x2) -> $(foldr 'a 'b1) x1 ( $(foldr 'a 'b2) x2 z )
  $(foldr 'a '(T b1 b2)) =  \x z -> foldr $(foldr 'a 'b2) z x  -- when a only occurs in the last parameter, b2

Note that the arguments to the real foldr function are the wrong way around,
since (f :: a -> b -> b), while (foldr f :: b -> t a -> b).

One can envision a case for types that don't contain the last type variable:

  $(foldr 'a 'b)         =  \x z -> z     -- when b does not contain a

But this case will never materialize, since the aforementioned filtering
removes all such types from consideration.
See Note [Generated code for DeriveFoldable and DeriveTraversable].

Foldable instances differ from Functor and Traversable instances in that
Foldable instances can be derived for data types in which the last type
variable is existentially quantified. In particular, if the last type variable
is refined to a more specific type in a GADT:

  data GADT a where
      G :: a ~ Int => a -> G Int

then the deriving machinery does not attempt to check that the type a contains
Int, since it is not syntactically equal to a type variable. That is, the
derived Foldable instance for GADT is:

  instance Foldable GADT where
      foldr _ z (GADT _) = z

See Note [DeriveFoldable with ExistentialQuantification].

Note [Deriving null]
~~~~~~~~~~~~~~~~~~~~

In some cases, deriving the definition of 'null' can produce much better
results than the default definition. For example, with

  data SnocList a = Nil | Snoc (SnocList a) a

the default definition of 'null' would walk the entire spine of a
nonempty snoc-list before concluding that it is not null. But looking at
the Snoc constructor, we can immediately see that it contains an 'a', and
so 'null' can return False immediately if it matches on Snoc. When we
derive 'null', we keep track of things that cannot be null. The interesting
case is type application. Given

  data Wrap a = Wrap (Foo (Bar a))

we use

  null (Wrap fba) = all null fba

but if we see

  data Wrap a = Wrap (Foo a)

we can just use

  null (Wrap fa) = null fa

Indeed, we allow this to happen even for tuples:

  data Wrap a = Wrap (Foo (a, Int))

produces

  null (Wrap fa) = null fa

As explained in Note [Deriving <$], giving tuples special performance treatment
could surprise users if they switch to other types, but Ryan Scott seems to
think it's okay to do it for now.
-}

gen_Foldable_binds :: SrcSpan -> TyCon -> [Type] -> (LHsBinds GhcPs, BagDerivStuff)
-- When the parameter is phantom, we can use foldMap _ _ = mempty
-- See Note [Phantom types with Functor, Foldable, and Traversable]
gen_Foldable_binds :: SrcSpan -> TyCon -> [Type] -> (LHsBinds GhcPs, BagDerivStuff)
gen_Foldable_binds SrcSpan
loc TyCon
tycon [Type]
_
  | Role
Phantom <- [Role] -> Role
forall a. [a] -> a
last (TyCon -> [Role]
tyConRoles TyCon
tycon)
  = (Located (HsBindLR GhcPs GhcPs)
-> Bag (Located (HsBindLR GhcPs GhcPs))
forall a. a -> Bag a
unitBag Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
foldMap_bind, BagDerivStuff
forall a. Bag a
emptyBag)
  where
    foldMap_name :: GenLocated SrcSpan RdrName
foldMap_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
foldMap_RDR
    foldMap_bind :: LHsBind GhcPs
foldMap_bind = GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)] -> LHsBind GhcPs
mkRdrFunBind GenLocated SrcSpan RdrName
foldMap_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
foldMap_eqns
    foldMap_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
foldMap_eqns = [HsMatchContext (NoGhcTc GhcPs)
-> [LPat GhcPs]
-> Located (HsExpr GhcPs)
-> LMatch GhcPs (Located (HsExpr GhcPs))
forall (p :: Pass) (body :: * -> *).
HsMatchContext (NoGhcTc (GhcPass p))
-> [LPat (GhcPass p)]
-> Located (body (GhcPass p))
-> LMatch (GhcPass p) (Located (body (GhcPass p)))
mkSimpleMatch HsMatchContext GhcPs
HsMatchContext (NoGhcTc GhcPs)
foldMap_match_ctxt
                                  [LPat GhcPs
nlWildPat, LPat GhcPs
nlWildPat]
                                  Located (HsExpr GhcPs)
LHsExpr GhcPs
mempty_Expr]
    foldMap_match_ctxt :: HsMatchContext GhcPs
foldMap_match_ctxt = LIdP GhcPs -> HsMatchContext GhcPs
forall p. LIdP p -> HsMatchContext p
mkPrefixFunRhs GenLocated SrcSpan RdrName
LIdP GhcPs
foldMap_name

gen_Foldable_binds SrcSpan
loc TyCon
tycon [Type]
tycon_args
  | [DataCon] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [DataCon]
data_cons  -- There's no real point producing anything but
                    -- foldMap for a type with no constructors.
  = (Located (HsBindLR GhcPs GhcPs)
-> Bag (Located (HsBindLR GhcPs GhcPs))
forall a. a -> Bag a
unitBag Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
foldMap_bind, BagDerivStuff
forall a. Bag a
emptyBag)

  | Bool
otherwise
  = ([Located (HsBindLR GhcPs GhcPs)]
-> Bag (Located (HsBindLR GhcPs GhcPs))
forall a. [a] -> Bag a
listToBag [Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
foldr_bind, Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
foldMap_bind, Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
null_bind], BagDerivStuff
forall a. Bag a
emptyBag)
  where
    data_cons :: [DataCon]
data_cons = TyCon -> [Type] -> [DataCon]
getPossibleDataCons TyCon
tycon [Type]
tycon_args

    foldr_bind :: LHsBind GhcPs
foldr_bind = GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)] -> LHsBind GhcPs
mkRdrFunBind (SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
foldable_foldr_RDR) [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
eqns
    eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
eqns = (DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [DataCon] -> [Located (Match GhcPs (Located (HsExpr GhcPs)))]
forall a b. (a -> b) -> [a] -> [b]
map DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
foldr_eqn [DataCon]
data_cons
    foldr_eqn :: DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
foldr_eqn DataCon
con
      = State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall s a. State s a -> s -> a
evalState (LHsExpr GhcPs
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
LHsExpr GhcPs
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_foldr LHsExpr GhcPs
z_Expr [LPat GhcPs
f_Pat,LPat GhcPs
z_Pat] DataCon
con ([Maybe (Located (HsExpr GhcPs))]
 -> State
      [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs)))))
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< State [RdrName] [Maybe (Located (HsExpr GhcPs))]
parts) [RdrName]
bs_RDRs
      where
        parts :: State [RdrName] [Maybe (Located (HsExpr GhcPs))]
parts = [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
 -> State [RdrName] [Maybe (Located (HsExpr GhcPs))])
-> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall a b. (a -> b) -> a -> b
$ FFoldType (State [RdrName] (Maybe (Located (HsExpr GhcPs))))
-> DataCon -> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
forall a. FFoldType a -> DataCon -> [a]
foldDataConArgs FFoldType (State [RdrName] (Maybe (Located (HsExpr GhcPs))))
FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
ft_foldr DataCon
con

    foldMap_name :: GenLocated SrcSpan RdrName
foldMap_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
foldMap_RDR

    -- See Note [EmptyDataDecls with Functor, Foldable, and Traversable]
    foldMap_bind :: LHsBind GhcPs
foldMap_bind = Arity
-> (LHsExpr GhcPs -> LHsExpr GhcPs)
-> GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)]
-> LHsBind GhcPs
mkRdrFunBindEC Arity
2 (Located (HsExpr GhcPs)
-> Located (HsExpr GhcPs) -> Located (HsExpr GhcPs)
forall a b. a -> b -> a
const Located (HsExpr GhcPs)
LHsExpr GhcPs
mempty_Expr)
                      GenLocated SrcSpan RdrName
foldMap_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
foldMap_eqns

    foldMap_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
foldMap_eqns = (DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [DataCon] -> [Located (Match GhcPs (Located (HsExpr GhcPs)))]
forall a b. (a -> b) -> [a] -> [b]
map DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
foldMap_eqn [DataCon]
data_cons

    foldMap_eqn :: DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
foldMap_eqn DataCon
con
      = State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall s a. State s a -> s -> a
evalState ([LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
[LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_foldMap [LPat GhcPs
f_Pat] DataCon
con ([Maybe (Located (HsExpr GhcPs))]
 -> State
      [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs)))))
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< State [RdrName] [Maybe (Located (HsExpr GhcPs))]
parts) [RdrName]
bs_RDRs
      where
        parts :: State [RdrName] [Maybe (Located (HsExpr GhcPs))]
parts = [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
 -> State [RdrName] [Maybe (Located (HsExpr GhcPs))])
-> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall a b. (a -> b) -> a -> b
$ FFoldType (State [RdrName] (Maybe (Located (HsExpr GhcPs))))
-> DataCon -> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
forall a. FFoldType a -> DataCon -> [a]
foldDataConArgs FFoldType (State [RdrName] (Maybe (Located (HsExpr GhcPs))))
FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
ft_foldMap DataCon
con

    -- Given a list of NullM results, produce Nothing if any of
    -- them is NotNull, and otherwise produce a list of Maybes
    -- with Justs representing unknowns and Nothings representing
    -- things that are definitely null.
    convert :: [NullM a] -> Maybe [Maybe a]
    convert :: [NullM a] -> Maybe [Maybe a]
convert = (NullM a -> Maybe (Maybe a)) -> [NullM a] -> Maybe [Maybe a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse NullM a -> Maybe (Maybe a)
forall a. NullM a -> Maybe (Maybe a)
go where
      go :: NullM a -> Maybe (Maybe a)
go NullM a
IsNull = Maybe a -> Maybe (Maybe a)
forall a. a -> Maybe a
Just Maybe a
forall a. Maybe a
Nothing
      go NullM a
NotNull = Maybe (Maybe a)
forall a. Maybe a
Nothing
      go (NullM a
a) = Maybe a -> Maybe (Maybe a)
forall a. a -> Maybe a
Just (a -> Maybe a
forall a. a -> Maybe a
Just a
a)

    null_name :: GenLocated SrcSpan RdrName
null_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
null_RDR
    null_match_ctxt :: HsMatchContext GhcPs
null_match_ctxt = LIdP GhcPs -> HsMatchContext GhcPs
forall p. LIdP p -> HsMatchContext p
mkPrefixFunRhs GenLocated SrcSpan RdrName
LIdP GhcPs
null_name
    null_bind :: LHsBind GhcPs
null_bind = GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)] -> LHsBind GhcPs
mkRdrFunBind GenLocated SrcSpan RdrName
null_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
null_eqns
    null_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
null_eqns = (DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [DataCon] -> [Located (Match GhcPs (Located (HsExpr GhcPs)))]
forall a b. (a -> b) -> [a] -> [b]
map DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
null_eqn [DataCon]
data_cons
    null_eqn :: DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
null_eqn DataCon
con
      = (State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
 -> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName]
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall a b c. (a -> b -> c) -> b -> a -> c
flip State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall s a. State s a -> s -> a
evalState [RdrName]
bs_RDRs (State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
 -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall a b. (a -> b) -> a -> b
$ do
          [NullM (Located (HsExpr GhcPs))]
parts <- [State [RdrName] (NullM (Located (HsExpr GhcPs)))]
-> State [RdrName] [NullM (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([State [RdrName] (NullM (Located (HsExpr GhcPs)))]
 -> State [RdrName] [NullM (Located (HsExpr GhcPs))])
-> [State [RdrName] (NullM (Located (HsExpr GhcPs)))]
-> State [RdrName] [NullM (Located (HsExpr GhcPs))]
forall a b. (a -> b) -> a -> b
$ FFoldType (State [RdrName] (NullM (Located (HsExpr GhcPs))))
-> DataCon -> [State [RdrName] (NullM (Located (HsExpr GhcPs)))]
forall a. FFoldType a -> DataCon -> [a]
foldDataConArgs FFoldType (State [RdrName] (NullM (Located (HsExpr GhcPs))))
FFoldType (State [RdrName] (NullM (LHsExpr GhcPs)))
ft_null DataCon
con
          case [NullM (Located (HsExpr GhcPs))]
-> Maybe [Maybe (Located (HsExpr GhcPs))]
forall a. [NullM a] -> Maybe [Maybe a]
convert [NullM (Located (HsExpr GhcPs))]
parts of
            Maybe [Maybe (Located (HsExpr GhcPs))]
Nothing -> Located (Match GhcPs (Located (HsExpr GhcPs)))
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (Match GhcPs (Located (HsExpr GhcPs)))
 -> State
      [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs)))))
-> Located (Match GhcPs (Located (HsExpr GhcPs)))
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall a b. (a -> b) -> a -> b
$
              HsMatchContext (NoGhcTc GhcPs)
-> [LPat GhcPs]
-> LHsExpr GhcPs
-> Located (HsLocalBinds GhcPs)
-> LMatch GhcPs (LHsExpr GhcPs)
forall (p :: Pass).
IsPass p =>
HsMatchContext (NoGhcTc (GhcPass p))
-> [LPat (GhcPass p)]
-> LHsExpr (GhcPass p)
-> Located (HsLocalBinds (GhcPass p))
-> LMatch (GhcPass p) (LHsExpr (GhcPass p))
mkMatch HsMatchContext GhcPs
HsMatchContext (NoGhcTc GhcPs)
null_match_ctxt [LPat GhcPs -> LPat GhcPs
forall (name :: Pass). LPat (GhcPass name) -> LPat (GhcPass name)
nlParPat (DataCon -> LPat GhcPs
nlWildConPat DataCon
con)]
                LHsExpr GhcPs
false_Expr (HsLocalBinds GhcPs -> Located (HsLocalBinds GhcPs)
forall e. e -> Located e
noLoc HsLocalBinds GhcPs
forall (a :: Pass) (b :: Pass).
HsLocalBindsLR (GhcPass a) (GhcPass b)
emptyLocalBinds)
            Just [Maybe (Located (HsExpr GhcPs))]
cp -> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
[LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_null [] DataCon
con [Maybe (Located (HsExpr GhcPs))]
[Maybe (LHsExpr GhcPs)]
cp

    -- Yields 'Just' an expression if we're folding over a type that mentions
    -- the last type parameter of the datatype. Otherwise, yields 'Nothing'.
    -- See Note [FFoldType and functorLikeTraverse]
    ft_foldr :: FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
    ft_foldr :: FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
ft_foldr
      = FT :: forall a.
a
-> a
-> a
-> (a -> a -> a)
-> (TyCon -> [a] -> a)
-> (Type -> Type -> a -> a)
-> a
-> (TcTyVar -> a -> a)
-> FFoldType a
FT { ft_triv :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_triv    = Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Located (HsExpr GhcPs))
forall a. Maybe a
Nothing
             -- foldr f = \x z -> z
           , ft_var :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_var     = Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Located (HsExpr GhcPs))
 -> State [RdrName] (Maybe (Located (HsExpr GhcPs))))
-> Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a b. (a -> b) -> a -> b
$ Located (HsExpr GhcPs) -> Maybe (Located (HsExpr GhcPs))
forall a. a -> Maybe a
Just Located (HsExpr GhcPs)
LHsExpr GhcPs
f_Expr
             -- foldr f = f
           , ft_tup :: TyCon
-> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_tup     = \TyCon
t [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
g -> do
               [Maybe (Located (HsExpr GhcPs))]
gg  <- [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
g
               Located (HsExpr GhcPs)
lam <- (LHsExpr GhcPs -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam2 ((LHsExpr GhcPs
  -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
 -> State [RdrName] (LHsExpr GhcPs))
-> (LHsExpr GhcPs
    -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
forall a b. (a -> b) -> a -> b
$ \LHsExpr GhcPs
x LHsExpr GhcPs
z ->
                 ([LPat GhcPs]
 -> DataCon
 -> [Maybe (Located (HsExpr GhcPs))]
 -> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon
-> [Maybe (Located (HsExpr GhcPs))]
-> LHsExpr GhcPs
-> State [RdrName] (LHsExpr GhcPs)
forall (m :: * -> *) a.
Monad m =>
([LPat GhcPs]
 -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase (LHsExpr GhcPs
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
LHsExpr GhcPs
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_foldr LHsExpr GhcPs
z) TyCon
t [Maybe (Located (HsExpr GhcPs))]
gg LHsExpr GhcPs
x
               Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (HsExpr GhcPs) -> Maybe (Located (HsExpr GhcPs))
forall a. a -> Maybe a
Just Located (HsExpr GhcPs)
lam)
             -- foldr f = (\x z -> case x of ...)
           , ft_ty_app :: Type
-> Type
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_ty_app  = \Type
_ Type
_ State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g -> do
               Maybe (Located (HsExpr GhcPs))
gg <- State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g
               (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\Located (HsExpr GhcPs)
gg' -> (LHsExpr GhcPs -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam2 ((LHsExpr GhcPs
  -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
 -> State [RdrName] (LHsExpr GhcPs))
-> (LHsExpr GhcPs
    -> LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
forall a b. (a -> b) -> a -> b
$ \LHsExpr GhcPs
x LHsExpr GhcPs
z -> Located (HsExpr GhcPs) -> State [RdrName] (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (HsExpr GhcPs)
 -> State [RdrName] (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs)
-> State [RdrName] (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$
                 IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
foldable_foldr_RDR [Located (HsExpr GhcPs)
LHsExpr GhcPs
gg',LHsExpr GhcPs
z,LHsExpr GhcPs
x]) Maybe (Located (HsExpr GhcPs))
gg
             -- foldr f = (\x z -> foldr g z x)
           , ft_forall :: TcTyVar
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_forall  = \TcTyVar
_ State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g
           , ft_co_var :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_co_var  = String -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"contravariant in ft_foldr"
           , ft_fun :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_fun     = String
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"function in ft_foldr"
           , ft_bad_app :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_bad_app = String -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"in other argument in ft_foldr" }

    match_foldr :: Monad m
                => LHsExpr GhcPs
                -> [LPat GhcPs]
                -> DataCon
                -> [Maybe (LHsExpr GhcPs)]
                -> m (LMatch GhcPs (LHsExpr GhcPs))
    match_foldr :: LHsExpr GhcPs
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_foldr LHsExpr GhcPs
z = HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch2 HsMatchContext GhcPs
forall p. HsMatchContext p
LambdaExpr ((LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
 -> [LPat GhcPs]
 -> DataCon
 -> [Maybe (LHsExpr GhcPs)]
 -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ \LHsExpr GhcPs
_ [LHsExpr GhcPs]
xs -> Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return ([LHsExpr GhcPs] -> LHsExpr GhcPs
mkFoldr [LHsExpr GhcPs]
xs)
      where
        -- g1 v1 (g2 v2 (.. z))
        mkFoldr :: [LHsExpr GhcPs] -> LHsExpr GhcPs
        mkFoldr :: [LHsExpr GhcPs] -> LHsExpr GhcPs
mkFoldr = (Located (HsExpr GhcPs)
 -> Located (HsExpr GhcPs) -> Located (HsExpr GhcPs))
-> Located (HsExpr GhcPs)
-> [Located (HsExpr GhcPs)]
-> Located (HsExpr GhcPs)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Located (HsExpr GhcPs)
-> Located (HsExpr GhcPs) -> Located (HsExpr GhcPs)
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp Located (HsExpr GhcPs)
LHsExpr GhcPs
z

    -- See Note [FFoldType and functorLikeTraverse]
    ft_foldMap :: FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
    ft_foldMap :: FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
ft_foldMap
      = FT :: forall a.
a
-> a
-> a
-> (a -> a -> a)
-> (TyCon -> [a] -> a)
-> (Type -> Type -> a -> a)
-> a
-> (TcTyVar -> a -> a)
-> FFoldType a
FT { ft_triv :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_triv = Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Located (HsExpr GhcPs))
forall a. Maybe a
Nothing
             -- foldMap f = \x -> mempty
           , ft_var :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_var  = Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (HsExpr GhcPs) -> Maybe (Located (HsExpr GhcPs))
forall a. a -> Maybe a
Just Located (HsExpr GhcPs)
LHsExpr GhcPs
f_Expr)
             -- foldMap f = f
           , ft_tup :: TyCon
-> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_tup  = \TyCon
t [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
g -> do
               [Maybe (Located (HsExpr GhcPs))]
gg  <- [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
g
               Located (HsExpr GhcPs)
lam <- (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam ((LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
 -> State [RdrName] (LHsExpr GhcPs))
-> (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
forall a b. (a -> b) -> a -> b
$ ([LPat GhcPs]
 -> DataCon
 -> [Maybe (Located (HsExpr GhcPs))]
 -> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon
-> [Maybe (Located (HsExpr GhcPs))]
-> LHsExpr GhcPs
-> State [RdrName] (LHsExpr GhcPs)
forall (m :: * -> *) a.
Monad m =>
([LPat GhcPs]
 -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase [LPat GhcPs]
-> DataCon
-> [Maybe (Located (HsExpr GhcPs))]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
[LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_foldMap TyCon
t [Maybe (Located (HsExpr GhcPs))]
gg
               Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (HsExpr GhcPs) -> Maybe (Located (HsExpr GhcPs))
forall a. a -> Maybe a
Just Located (HsExpr GhcPs)
lam)
             -- foldMap f = \x -> case x of (..,)
           , ft_ty_app :: Type
-> Type
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_ty_app = \Type
_ Type
_ State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g -> (Located (HsExpr GhcPs) -> Located (HsExpr GhcPs))
-> Maybe (Located (HsExpr GhcPs)) -> Maybe (Located (HsExpr GhcPs))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp LHsExpr GhcPs
foldMap_Expr) (Maybe (Located (HsExpr GhcPs)) -> Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g
             -- foldMap f = foldMap g
           , ft_forall :: TcTyVar
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_forall = \TcTyVar
_ State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g
           , ft_co_var :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_co_var = String -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"contravariant in ft_foldMap"
           , ft_fun :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_fun = String
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"function in ft_foldMap"
           , ft_bad_app :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_bad_app = String -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"in other argument in ft_foldMap" }

    match_foldMap :: Monad m
                  => [LPat GhcPs]
                  -> DataCon
                  -> [Maybe (LHsExpr GhcPs)]
                  -> m (LMatch GhcPs (LHsExpr GhcPs))
    match_foldMap :: [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_foldMap = HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch2 HsMatchContext GhcPs
forall p. HsMatchContext p
CaseAlt ((LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
 -> [LPat GhcPs]
 -> DataCon
 -> [Maybe (LHsExpr GhcPs)]
 -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ \LHsExpr GhcPs
_ [LHsExpr GhcPs]
xs -> Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return ([LHsExpr GhcPs] -> LHsExpr GhcPs
mkFoldMap [LHsExpr GhcPs]
xs)
      where
        -- mappend v1 (mappend v2 ..)
        mkFoldMap :: [LHsExpr GhcPs] -> LHsExpr GhcPs
        mkFoldMap :: [LHsExpr GhcPs] -> LHsExpr GhcPs
mkFoldMap [] = LHsExpr GhcPs
mempty_Expr
        mkFoldMap [LHsExpr GhcPs]
xs = (Located (HsExpr GhcPs)
 -> Located (HsExpr GhcPs) -> Located (HsExpr GhcPs))
-> [Located (HsExpr GhcPs)] -> Located (HsExpr GhcPs)
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (\Located (HsExpr GhcPs)
x Located (HsExpr GhcPs)
y -> IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
mappend_RDR [Located (HsExpr GhcPs)
LHsExpr GhcPs
x,Located (HsExpr GhcPs)
LHsExpr GhcPs
y]) [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
xs

    -- See Note [FFoldType and functorLikeTraverse]
    -- Yields NullM an expression if we're folding over an expression
    -- that may or may not be null. Yields IsNull if it's certainly
    -- null, and yields NotNull if it's certainly not null.
    -- See Note [Deriving null]
    ft_null :: FFoldType (State [RdrName] (NullM (LHsExpr GhcPs)))
    ft_null :: FFoldType (State [RdrName] (NullM (LHsExpr GhcPs)))
ft_null
      = FT :: forall a.
a
-> a
-> a
-> (a -> a -> a)
-> (TyCon -> [a] -> a)
-> (Type -> Type -> a -> a)
-> a
-> (TcTyVar -> a -> a)
-> FFoldType a
FT { ft_triv :: State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_triv = NullM (Located (HsExpr GhcPs))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return NullM (Located (HsExpr GhcPs))
forall a. NullM a
IsNull
             -- null = \_ -> True
           , ft_var :: State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_var  = NullM (Located (HsExpr GhcPs))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return NullM (Located (HsExpr GhcPs))
forall a. NullM a
NotNull
             -- null = \_ -> False
           , ft_tup :: TyCon
-> [State [RdrName] (NullM (Located (HsExpr GhcPs)))]
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_tup  = \TyCon
t [State [RdrName] (NullM (Located (HsExpr GhcPs)))]
g -> do
               [NullM (Located (HsExpr GhcPs))]
gg  <- [State [RdrName] (NullM (Located (HsExpr GhcPs)))]
-> State [RdrName] [NullM (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [State [RdrName] (NullM (Located (HsExpr GhcPs)))]
g
               case [NullM (Located (HsExpr GhcPs))]
-> Maybe [Maybe (Located (HsExpr GhcPs))]
forall a. [NullM a] -> Maybe [Maybe a]
convert [NullM (Located (HsExpr GhcPs))]
gg of
                 Maybe [Maybe (Located (HsExpr GhcPs))]
Nothing -> NullM (Located (HsExpr GhcPs))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall (f :: * -> *) a. Applicative f => a -> f a
pure NullM (Located (HsExpr GhcPs))
forall a. NullM a
NotNull
                 Just [Maybe (Located (HsExpr GhcPs))]
ggg ->
                   Located (HsExpr GhcPs) -> NullM (Located (HsExpr GhcPs))
forall a. a -> NullM a
NullM (Located (HsExpr GhcPs) -> NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (Located (HsExpr GhcPs))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam ((LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
 -> State [RdrName] (LHsExpr GhcPs))
-> (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
forall a b. (a -> b) -> a -> b
$ ([LPat GhcPs]
 -> DataCon
 -> [Maybe (Located (HsExpr GhcPs))]
 -> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon
-> [Maybe (Located (HsExpr GhcPs))]
-> LHsExpr GhcPs
-> State [RdrName] (LHsExpr GhcPs)
forall (m :: * -> *) a.
Monad m =>
([LPat GhcPs]
 -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase [LPat GhcPs]
-> DataCon
-> [Maybe (Located (HsExpr GhcPs))]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
[LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_null TyCon
t [Maybe (Located (HsExpr GhcPs))]
ggg)
             -- null = \x -> case x of (..,)
           , ft_ty_app :: Type
-> Type
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_ty_app = \Type
_ Type
_ State [RdrName] (NullM (Located (HsExpr GhcPs)))
g -> ((NullM (Located (HsExpr GhcPs)) -> NullM (Located (HsExpr GhcPs)))
 -> State [RdrName] (NullM (Located (HsExpr GhcPs)))
 -> State [RdrName] (NullM (Located (HsExpr GhcPs))))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> (NullM (Located (HsExpr GhcPs))
    -> NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall a b c. (a -> b -> c) -> b -> a -> c
flip (NullM (Located (HsExpr GhcPs)) -> NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap State [RdrName] (NullM (Located (HsExpr GhcPs)))
g ((NullM (Located (HsExpr GhcPs)) -> NullM (Located (HsExpr GhcPs)))
 -> State [RdrName] (NullM (Located (HsExpr GhcPs))))
-> (NullM (Located (HsExpr GhcPs))
    -> NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall a b. (a -> b) -> a -> b
$ \NullM (Located (HsExpr GhcPs))
nestedResult ->
                              case NullM (Located (HsExpr GhcPs))
nestedResult of
                                -- If e definitely contains the parameter,
                                -- then we can test if (G e) contains it by
                                -- simply checking if (G e) is null
                                NullM (Located (HsExpr GhcPs))
NotNull -> Located (HsExpr GhcPs) -> NullM (Located (HsExpr GhcPs))
forall a. a -> NullM a
NullM Located (HsExpr GhcPs)
LHsExpr GhcPs
null_Expr
                                -- This case is unreachable--it will actually be
                                -- caught by ft_triv
                                NullM (Located (HsExpr GhcPs))
IsNull -> NullM (Located (HsExpr GhcPs))
forall a. NullM a
IsNull
                                -- The general case uses (all null),
                                -- (all (all null)), etc.
                                NullM Located (HsExpr GhcPs)
nestedTest -> Located (HsExpr GhcPs) -> NullM (Located (HsExpr GhcPs))
forall a. a -> NullM a
NullM (Located (HsExpr GhcPs) -> NullM (Located (HsExpr GhcPs)))
-> Located (HsExpr GhcPs) -> NullM (Located (HsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$
                                                    LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp LHsExpr GhcPs
all_Expr Located (HsExpr GhcPs)
LHsExpr GhcPs
nestedTest
             -- null fa = null fa, or null fa = all null fa, or null fa = True
           , ft_forall :: TcTyVar
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_forall = \TcTyVar
_ State [RdrName] (NullM (Located (HsExpr GhcPs)))
g -> State [RdrName] (NullM (Located (HsExpr GhcPs)))
g
           , ft_co_var :: State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_co_var = String -> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"contravariant in ft_null"
           , ft_fun :: State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_fun = String
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
-> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"function in ft_null"
           , ft_bad_app :: State [RdrName] (NullM (Located (HsExpr GhcPs)))
ft_bad_app = String -> State [RdrName] (NullM (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"in other argument in ft_null" }

    match_null :: Monad m
               => [LPat GhcPs]
               -> DataCon
               -> [Maybe (LHsExpr GhcPs)]
               -> m (LMatch GhcPs (LHsExpr GhcPs))
    match_null :: [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_null = HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch2 HsMatchContext GhcPs
forall p. HsMatchContext p
CaseAlt ((LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
 -> [LPat GhcPs]
 -> DataCon
 -> [Maybe (LHsExpr GhcPs)]
 -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$ \LHsExpr GhcPs
_ [LHsExpr GhcPs]
xs -> Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return ([LHsExpr GhcPs] -> LHsExpr GhcPs
mkNull [LHsExpr GhcPs]
xs)
      where
        -- v1 && v2 && ..
        mkNull :: [LHsExpr GhcPs] -> LHsExpr GhcPs
        mkNull :: [LHsExpr GhcPs] -> LHsExpr GhcPs
mkNull [] = LHsExpr GhcPs
true_Expr
        mkNull [LHsExpr GhcPs]
xs = (Located (HsExpr GhcPs)
 -> Located (HsExpr GhcPs) -> Located (HsExpr GhcPs))
-> [Located (HsExpr GhcPs)] -> Located (HsExpr GhcPs)
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (\Located (HsExpr GhcPs)
x Located (HsExpr GhcPs)
y -> IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
and_RDR [Located (HsExpr GhcPs)
LHsExpr GhcPs
x,Located (HsExpr GhcPs)
LHsExpr GhcPs
y]) [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
xs

data NullM a =
    IsNull   -- Definitely null
  | NotNull  -- Definitely not null
  | NullM a  -- Unknown

{-
************************************************************************
*                                                                      *
                        Traversable instances

 see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
*                                                                      *
************************************************************************

Again, Traversable is much like Functor and Foldable.

The cases are:

  $(traverse 'a 'a)          =  f
  $(traverse 'a '(b1,b2))    =  \x -> case x of (x1,x2) ->
     liftA2 (,) ($(traverse 'a 'b1) x1) ($(traverse 'a 'b2) x2)
  $(traverse 'a '(T b1 b2))  =  traverse $(traverse 'a 'b2)  -- when a only occurs in the last parameter, b2

Like -XDeriveFoldable, -XDeriveTraversable filters out arguments whose types
do not mention the last type parameter. Therefore, the following datatype:

  data Foo a = Foo Int a Int

would have the following derived Traversable instance:

  instance Traversable Foo where
    traverse f (Foo x1 x2 x3) =
      fmap (\b2 -> Foo x1 b2 x3) ( $(traverse 'a 'a) x2 )

since the two Int arguments do not produce any effects in a traversal.

One can envision a case for types that do not mention the last type parameter:

  $(traverse 'a 'b)          =  pure     -- when b does not contain a

But this case will never materialize, since the aforementioned filtering
removes all such types from consideration.
See Note [Generated code for DeriveFoldable and DeriveTraversable].
-}

gen_Traversable_binds :: SrcSpan -> TyCon -> [Type] -> (LHsBinds GhcPs, BagDerivStuff)
-- When the argument is phantom, we can use traverse = pure . coerce
-- See Note [Phantom types with Functor, Foldable, and Traversable]
gen_Traversable_binds :: SrcSpan -> TyCon -> [Type] -> (LHsBinds GhcPs, BagDerivStuff)
gen_Traversable_binds SrcSpan
loc TyCon
tycon [Type]
_
  | Role
Phantom <- [Role] -> Role
forall a. [a] -> a
last (TyCon -> [Role]
tyConRoles TyCon
tycon)
  = (Located (HsBindLR GhcPs GhcPs)
-> Bag (Located (HsBindLR GhcPs GhcPs))
forall a. a -> Bag a
unitBag Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
traverse_bind, BagDerivStuff
forall a. Bag a
emptyBag)
  where
    traverse_name :: GenLocated SrcSpan RdrName
traverse_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
traverse_RDR
    traverse_bind :: LHsBind GhcPs
traverse_bind = GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)] -> LHsBind GhcPs
mkRdrFunBind GenLocated SrcSpan RdrName
traverse_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
traverse_eqns
    traverse_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
traverse_eqns =
        [HsMatchContext (NoGhcTc GhcPs)
-> [LPat GhcPs]
-> Located (HsExpr GhcPs)
-> LMatch GhcPs (Located (HsExpr GhcPs))
forall (p :: Pass) (body :: * -> *).
HsMatchContext (NoGhcTc (GhcPass p))
-> [LPat (GhcPass p)]
-> Located (body (GhcPass p))
-> LMatch (GhcPass p) (Located (body (GhcPass p)))
mkSimpleMatch HsMatchContext GhcPs
HsMatchContext (NoGhcTc GhcPs)
traverse_match_ctxt
                       [LPat GhcPs
nlWildPat, LPat GhcPs
z_Pat]
                       (IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
pure_RDR [LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp LHsExpr GhcPs
coerce_Expr LHsExpr GhcPs
z_Expr])]
    traverse_match_ctxt :: HsMatchContext GhcPs
traverse_match_ctxt = LIdP GhcPs -> HsMatchContext GhcPs
forall p. LIdP p -> HsMatchContext p
mkPrefixFunRhs GenLocated SrcSpan RdrName
LIdP GhcPs
traverse_name

gen_Traversable_binds SrcSpan
loc TyCon
tycon [Type]
tycon_args
  = (Located (HsBindLR GhcPs GhcPs)
-> Bag (Located (HsBindLR GhcPs GhcPs))
forall a. a -> Bag a
unitBag Located (HsBindLR GhcPs GhcPs)
LHsBind GhcPs
traverse_bind, BagDerivStuff
forall a. Bag a
emptyBag)
  where
    data_cons :: [DataCon]
data_cons = TyCon -> [Type] -> [DataCon]
getPossibleDataCons TyCon
tycon [Type]
tycon_args

    traverse_name :: GenLocated SrcSpan RdrName
traverse_name = SrcSpan -> RdrName -> GenLocated SrcSpan RdrName
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc RdrName
traverse_RDR

    -- See Note [EmptyDataDecls with Functor, Foldable, and Traversable]
    traverse_bind :: LHsBind GhcPs
traverse_bind = Arity
-> (LHsExpr GhcPs -> LHsExpr GhcPs)
-> GenLocated SrcSpan RdrName
-> [LMatch GhcPs (LHsExpr GhcPs)]
-> LHsBind GhcPs
mkRdrFunBindEC Arity
2 (LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp LHsExpr GhcPs
pure_Expr)
                                   GenLocated SrcSpan RdrName
traverse_name [Located (Match GhcPs (Located (HsExpr GhcPs)))]
[LMatch GhcPs (LHsExpr GhcPs)]
traverse_eqns
    traverse_eqns :: [Located (Match GhcPs (Located (HsExpr GhcPs)))]
traverse_eqns = (DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [DataCon] -> [Located (Match GhcPs (Located (HsExpr GhcPs)))]
forall a b. (a -> b) -> [a] -> [b]
map DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
traverse_eqn [DataCon]
data_cons
    traverse_eqn :: DataCon -> Located (Match GhcPs (Located (HsExpr GhcPs)))
traverse_eqn DataCon
con
      = State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
-> [RdrName] -> Located (Match GhcPs (Located (HsExpr GhcPs)))
forall s a. State s a -> s -> a
evalState ([LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
[LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con [LPat GhcPs
f_Pat] DataCon
con ([Maybe (Located (HsExpr GhcPs))]
 -> State
      [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs)))))
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
-> State [RdrName] (Located (Match GhcPs (Located (HsExpr GhcPs))))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< State [RdrName] [Maybe (Located (HsExpr GhcPs))]
parts) [RdrName]
bs_RDRs
      where
        parts :: State [RdrName] [Maybe (Located (HsExpr GhcPs))]
parts = [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
 -> State [RdrName] [Maybe (Located (HsExpr GhcPs))])
-> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall a b. (a -> b) -> a -> b
$ FFoldType (State [RdrName] (Maybe (Located (HsExpr GhcPs))))
-> DataCon -> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
forall a. FFoldType a -> DataCon -> [a]
foldDataConArgs FFoldType (State [RdrName] (Maybe (Located (HsExpr GhcPs))))
FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
ft_trav DataCon
con

    -- Yields 'Just' an expression if we're folding over a type that mentions
    -- the last type parameter of the datatype. Otherwise, yields 'Nothing'.
    -- See Note [FFoldType and functorLikeTraverse]
    ft_trav :: FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
    ft_trav :: FFoldType (State [RdrName] (Maybe (LHsExpr GhcPs)))
ft_trav
      = FT :: forall a.
a
-> a
-> a
-> (a -> a -> a)
-> (TyCon -> [a] -> a)
-> (Type -> Type -> a -> a)
-> a
-> (TcTyVar -> a -> a)
-> FFoldType a
FT { ft_triv :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_triv    = Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Located (HsExpr GhcPs))
forall a. Maybe a
Nothing
             -- traverse f = pure x
           , ft_var :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_var     = Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (HsExpr GhcPs) -> Maybe (Located (HsExpr GhcPs))
forall a. a -> Maybe a
Just Located (HsExpr GhcPs)
LHsExpr GhcPs
f_Expr)
             -- traverse f = f x
           , ft_tup :: TyCon
-> [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_tup     = \TyCon
t [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
gs -> do
               [Maybe (Located (HsExpr GhcPs))]
gg  <- [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
-> State [RdrName] [Maybe (Located (HsExpr GhcPs))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [State [RdrName] (Maybe (Located (HsExpr GhcPs)))]
gs
               Located (HsExpr GhcPs)
lam <- (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
mkSimpleLam ((LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
 -> State [RdrName] (LHsExpr GhcPs))
-> (LHsExpr GhcPs -> State [RdrName] (LHsExpr GhcPs))
-> State [RdrName] (LHsExpr GhcPs)
forall a b. (a -> b) -> a -> b
$ ([LPat GhcPs]
 -> DataCon
 -> [Maybe (Located (HsExpr GhcPs))]
 -> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon
-> [Maybe (Located (HsExpr GhcPs))]
-> LHsExpr GhcPs
-> State [RdrName] (LHsExpr GhcPs)
forall (m :: * -> *) a.
Monad m =>
([LPat GhcPs]
 -> DataCon -> [a] -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> TyCon -> [a] -> LHsExpr GhcPs -> m (LHsExpr GhcPs)
mkSimpleTupleCase [LPat GhcPs]
-> DataCon
-> [Maybe (Located (HsExpr GhcPs))]
-> State [RdrName] (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
[LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con TyCon
t [Maybe (Located (HsExpr GhcPs))]
gg
               Maybe (Located (HsExpr GhcPs))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Located (HsExpr GhcPs) -> Maybe (Located (HsExpr GhcPs))
forall a. a -> Maybe a
Just Located (HsExpr GhcPs)
lam)
             -- traverse f = \x -> case x of (a1,a2,..) ->
             --                           liftA2 (,,) (g1 a1) (g2 a2) <*> ..
           , ft_ty_app :: Type
-> Type
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_ty_app  = \Type
_ Type
_ State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g -> (Located (HsExpr GhcPs) -> Located (HsExpr GhcPs))
-> Maybe (Located (HsExpr GhcPs)) -> Maybe (Located (HsExpr GhcPs))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
LHsExpr (GhcPass id)
-> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
nlHsApp LHsExpr GhcPs
traverse_Expr) (Maybe (Located (HsExpr GhcPs)) -> Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g
             -- traverse f = traverse g
           , ft_forall :: TcTyVar
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_forall  = \TcTyVar
_ State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
g
           , ft_co_var :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_co_var  = String -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"contravariant in ft_trav"
           , ft_fun :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_fun     = String
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
-> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"function in ft_trav"
           , ft_bad_app :: State [RdrName] (Maybe (Located (HsExpr GhcPs)))
ft_bad_app = String -> State [RdrName] (Maybe (Located (HsExpr GhcPs)))
forall a. String -> a
panic String
"in other argument in ft_trav" }

    -- Con a1 a2 ... -> liftA2 (\b1 b2 ... -> Con b1 b2 ...) (g1 a1)
    --                    (g2 a2) <*> ...
    match_for_con :: Monad m
                  => [LPat GhcPs]
                  -> DataCon
                  -> [Maybe (LHsExpr GhcPs)]
                  -> m (LMatch GhcPs (LHsExpr GhcPs))
    match_for_con :: [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
match_for_con = HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall (m :: * -> *).
Monad m =>
HsMatchContext GhcPs
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
mkSimpleConMatch2 HsMatchContext GhcPs
forall p. HsMatchContext p
CaseAlt ((LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
 -> [LPat GhcPs]
 -> DataCon
 -> [Maybe (LHsExpr GhcPs)]
 -> m (LMatch GhcPs (LHsExpr GhcPs)))
-> (LHsExpr GhcPs -> [LHsExpr GhcPs] -> m (LHsExpr GhcPs))
-> [LPat GhcPs]
-> DataCon
-> [Maybe (LHsExpr GhcPs)]
-> m (LMatch GhcPs (LHsExpr GhcPs))
forall a b. (a -> b) -> a -> b
$
                                             \LHsExpr GhcPs
con [LHsExpr GhcPs]
xs -> Located (HsExpr GhcPs) -> m (Located (HsExpr GhcPs))
forall (m :: * -> *) a. Monad m => a -> m a
return (LHsExpr GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
mkApCon LHsExpr GhcPs
con [LHsExpr GhcPs]
xs)
      where
        -- liftA2 (\b1 b2 ... -> Con b1 b2 ...) x1 x2 <*> ..
        mkApCon :: LHsExpr GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
        mkApCon :: LHsExpr GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
mkApCon LHsExpr GhcPs
con [] = IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
pure_RDR [LHsExpr GhcPs
con]
        mkApCon LHsExpr GhcPs
con [LHsExpr GhcPs
x] = IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
fmap_RDR [LHsExpr GhcPs
con,LHsExpr GhcPs
x]
        mkApCon LHsExpr GhcPs
con (LHsExpr GhcPs
x1:LHsExpr GhcPs
x2:[LHsExpr GhcPs]
xs) =
            (Located (HsExpr GhcPs)
 -> Located (HsExpr GhcPs) -> Located (HsExpr GhcPs))
-> Located (HsExpr GhcPs)
-> [Located (HsExpr GhcPs)]
-> Located (HsExpr GhcPs)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Located (HsExpr GhcPs)
-> Located (HsExpr GhcPs) -> Located (HsExpr GhcPs)
forall (id :: Pass).
(IsPass id, IdGhcP id ~ RdrName) =>
GenLocated SrcSpan (HsExpr (GhcPass id))
-> GenLocated SrcSpan (HsExpr (GhcPass id))
-> GenLocated SrcSpan (HsExpr (GhcPass id))
appAp (IdP GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP GhcPs
liftA2_RDR [LHsExpr GhcPs
con,LHsExpr GhcPs
x1,LHsExpr GhcPs
x2]) [Located (HsExpr GhcPs)]
[LHsExpr GhcPs]
xs
          where appAp :: GenLocated SrcSpan (HsExpr (GhcPass id))
-> GenLocated SrcSpan (HsExpr (GhcPass id)) -> LHsExpr (GhcPass id)
appAp GenLocated SrcSpan (HsExpr (GhcPass id))
x GenLocated SrcSpan (HsExpr (GhcPass id))
y = IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
forall (id :: Pass).
IsPass id =>
IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
nlHsApps RdrName
IdP (GhcPass id)
ap_RDR [GenLocated SrcSpan (HsExpr (GhcPass id))
LHsExpr (GhcPass id)
x,GenLocated SrcSpan (HsExpr (GhcPass id))
LHsExpr (GhcPass id)
y]

-----------------------------------------------------------------------

f_Expr, z_Expr, mempty_Expr, foldMap_Expr,
    traverse_Expr, coerce_Expr, pure_Expr, true_Expr, false_Expr,
    all_Expr, null_Expr :: LHsExpr GhcPs
f_Expr :: LHsExpr GhcPs
f_Expr        = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
f_RDR
z_Expr :: LHsExpr GhcPs
z_Expr        = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
z_RDR
mempty_Expr :: LHsExpr GhcPs
mempty_Expr   = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
mempty_RDR
foldMap_Expr :: LHsExpr GhcPs
foldMap_Expr  = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
foldMap_RDR
traverse_Expr :: LHsExpr GhcPs
traverse_Expr = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
traverse_RDR
coerce_Expr :: LHsExpr GhcPs
coerce_Expr   = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar (TcTyVar -> RdrName
forall thing. NamedThing thing => thing -> RdrName
getRdrName TcTyVar
coerceId)
pure_Expr :: LHsExpr GhcPs
pure_Expr     = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
pure_RDR
true_Expr :: LHsExpr GhcPs
true_Expr     = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
true_RDR
false_Expr :: LHsExpr GhcPs
false_Expr    = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
false_RDR
all_Expr :: LHsExpr GhcPs
all_Expr      = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
all_RDR
null_Expr :: LHsExpr GhcPs
null_Expr     = IdP GhcPs -> LHsExpr GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar RdrName
IdP GhcPs
null_RDR

f_RDR, z_RDR :: RdrName
f_RDR :: RdrName
f_RDR = FastString -> RdrName
mkVarUnqual (String -> FastString
fsLit String
"f")
z_RDR :: RdrName
z_RDR = FastString -> RdrName
mkVarUnqual (String -> FastString
fsLit String
"z")

as_RDRs, bs_RDRs :: [RdrName]
as_RDRs :: [RdrName]
as_RDRs = [ FastString -> RdrName
mkVarUnqual (String -> FastString
mkFastString (String
"a"String -> String -> String
forall a. [a] -> [a] -> [a]
++Arity -> String
forall a. Show a => a -> String
show Arity
i)) | Arity
i <- [(Arity
1::Int) .. ] ]
bs_RDRs :: [RdrName]
bs_RDRs = [ FastString -> RdrName
mkVarUnqual (String -> FastString
mkFastString (String
"b"String -> String -> String
forall a. [a] -> [a] -> [a]
++Arity -> String
forall a. Show a => a -> String
show Arity
i)) | Arity
i <- [(Arity
1::Int) .. ] ]

as_Vars, bs_Vars :: [LHsExpr GhcPs]
as_Vars :: [LHsExpr GhcPs]
as_Vars = (RdrName -> Located (HsExpr GhcPs))
-> [RdrName] -> [Located (HsExpr GhcPs)]
forall a b. (a -> b) -> [a] -> [b]
map RdrName -> Located (HsExpr GhcPs)
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar [RdrName]
as_RDRs
bs_Vars :: [LHsExpr GhcPs]
bs_Vars = (RdrName -> Located (HsExpr GhcPs))
-> [RdrName] -> [Located (HsExpr GhcPs)]
forall a b. (a -> b) -> [a] -> [b]
map RdrName -> Located (HsExpr GhcPs)
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar [RdrName]
bs_RDRs

f_Pat, z_Pat :: LPat GhcPs
f_Pat :: LPat GhcPs
f_Pat = IdP GhcPs -> LPat GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LPat (GhcPass id)
nlVarPat RdrName
IdP GhcPs
f_RDR
z_Pat :: LPat GhcPs
z_Pat = IdP GhcPs -> LPat GhcPs
forall (id :: Pass). IdP (GhcPass id) -> LPat (GhcPass id)
nlVarPat RdrName
IdP GhcPs
z_RDR

{-
Note [DeriveFoldable with ExistentialQuantification]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functor and Traversable instances can only be derived for data types whose
last type parameter is truly universally polymorphic. For example:

  data T a b where
    T1 ::                 b   -> T a b   -- YES, b is unconstrained
    T2 :: Ord b   =>      b   -> T a b   -- NO, b is constrained by (Ord b)
    T3 :: b ~ Int =>      b   -> T a b   -- NO, b is constrained by (b ~ Int)
    T4 ::                 Int -> T a Int -- NO, this is just like T3
    T5 :: Ord a   => a -> b   -> T a b   -- YES, b is unconstrained, even
                                         -- though a is existential
    T6 ::                 Int -> T Int b -- YES, b is unconstrained

For Foldable instances, however, we can completely lift the constraint that
the last type parameter be truly universally polymorphic. This means that T
(as defined above) can have a derived Foldable instance:

  instance Foldable (T a) where
    foldr f z (T1 b)   = f b z
    foldr f z (T2 b)   = f b z
    foldr f z (T3 b)   = f b z
    foldr f z (T4 b)   = z
    foldr f z (T5 a b) = f b z
    foldr f z (T6 a)   = z

    foldMap f (T1 b)   = f b
    foldMap f (T2 b)   = f b
    foldMap f (T3 b)   = f b
    foldMap f (T4 b)   = mempty
    foldMap f (T5 a b) = f b
    foldMap f (T6 a)   = mempty

In a Foldable instance, it is safe to fold over an occurrence of the last type
parameter that is not truly universally polymorphic. However, there is a bit
of subtlety in determining what is actually an occurrence of a type parameter.
T3 and T4, as defined above, provide one example:

  data T a b where
    ...
    T3 :: b ~ Int => b   -> T a b
    T4 ::            Int -> T a Int
    ...

  instance Foldable (T a) where
    ...
    foldr f z (T3 b) = f b z
    foldr f z (T4 b) = z
    ...
    foldMap f (T3 b) = f b
    foldMap f (T4 b) = mempty
    ...

Notice that the argument of T3 is folded over, whereas the argument of T4 is
not. This is because we only fold over constructor arguments that
syntactically mention the universally quantified type parameter of that
particular data constructor. See foldDataConArgs for how this is implemented.

As another example, consider the following data type. The argument of each
constructor has the same type as the last type parameter:

  data E a where
    E1 :: (a ~ Int) => a   -> E a
    E2 ::              Int -> E Int
    E3 :: (a ~ Int) => a   -> E Int
    E4 :: (a ~ Int) => Int -> E a

Only E1's argument is an occurrence of a universally quantified type variable
that is syntactically equivalent to the last type parameter, so only E1's
argument will be folded over in a derived Foldable instance.

See #10447 for the original discussion on this feature. Also see
https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/derive-functor
for a more in-depth explanation.

Note [FFoldType and functorLikeTraverse]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Deriving Functor, Foldable, and Traversable all require generating expressions
which perform an operation on each argument of a data constructor depending
on the argument's type. In particular, a generated operation can be different
depending on whether the type mentions the last type variable of the datatype
(e.g., if you have data T a = MkT a Int, then a generated foldr expression would
fold over the first argument of MkT, but not the second).

This pattern is abstracted with the FFoldType datatype, which provides hooks
for the user to specify how a constructor argument should be folded when it
has a type with a particular "shape". The shapes are as follows (assume that
a is the last type variable in a given datatype):

* ft_triv:    The type does not mention the last type variable at all.
              Examples: Int, b

* ft_var:     The type is syntactically equal to the last type variable.
              Moreover, the type appears in a covariant position (see
              the Deriving Functor instances section of the user's guide
              for an in-depth explanation of covariance vs. contravariance).
              Example: a (covariantly)

* ft_co_var:  The type is syntactically equal to the last type variable.
              Moreover, the type appears in a contravariant position.
              Example: a (contravariantly)

* ft_fun:     A function type which mentions the last type variable in
              the argument position, result position or both.
              Examples: a -> Int, Int -> a, Maybe a -> [a]

* ft_tup:     A tuple type which mentions the last type variable in at least
              one of its fields. The TyCon argument of ft_tup represents the
              particular tuple's type constructor.
              Examples: (a, Int), (Maybe a, [a], Either a Int), (# Int, a #)

* ft_ty_app:  A type is being applied to the last type parameter, where the
              applied type does not mention the last type parameter (if it
              did, it would fall under ft_bad_app) and the argument type
              mentions the last type parameter (if it did not, it would fall
              under ft_triv). The first two Type arguments to
              ft_ty_app represent the applied type and argument type,
              respectively.

              Currently, only DeriveFunctor makes use of the argument type.
              It inspects the argument type so that it can generate more
              efficient implementations of fmap
              (see Note [Avoid unnecessary eta expansion in derived fmap implementations])
              and (<$) (see Note [Deriving <$]) in certain cases.

              Note that functions, tuples, and foralls are distinct cases
              and take precedence over ft_ty_app. (For example, (Int -> a) would
              fall under (ft_fun Int a), not (ft_ty_app ((->) Int) a).
              Examples: Maybe a, Either b a

* ft_bad_app: A type application uses the last type parameter in a position
              other than the last argument. This case is singled out because
              Functor, Foldable, and Traversable instances cannot be derived
              for datatypes containing arguments with such types.
              Examples: Either a Int, Const a b

* ft_forall:  A forall'd type mentions the last type parameter on its right-
              hand side (and is not quantified on the left-hand side). This
              case is present mostly for plumbing purposes.
              Example: forall b. Either b a

If FFoldType describes a strategy for folding subcomponents of a Type, then
functorLikeTraverse is the function that applies that strategy to the entirety
of a Type, returning the final folded-up result.

foldDataConArgs applies functorLikeTraverse to every argument type of a
constructor, returning a list of the fold results. This makes foldDataConArgs
a natural way to generate the subexpressions in a generated fmap, foldr,
foldMap, or traverse definition (the subexpressions must then be combined in
a method-specific fashion to form the final generated expression).

Deriving Generic1 also does validity checking by looking for the last type
variable in certain positions of a constructor's argument types, so it also
uses foldDataConArgs. See Note [degenerate use of FFoldType] in GHC.Tc.Deriv.Generics.

Note [Generated code for DeriveFoldable and DeriveTraversable]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We adapt the algorithms for -XDeriveFoldable and -XDeriveTraversable based on
that of -XDeriveFunctor. However, there an important difference between deriving
the former two typeclasses and the latter one, which is best illustrated by the
following scenario:

  data WithInt a = WithInt a Int# deriving (Functor, Foldable, Traversable)

The generated code for the Functor instance is straightforward:

  instance Functor WithInt where
    fmap f (WithInt a i) = WithInt (f a) i

But if we use too similar of a strategy for deriving the Foldable and
Traversable instances, we end up with this code:

  instance Foldable WithInt where
    foldMap f (WithInt a i) = f a <> mempty

  instance Traversable WithInt where
    traverse f (WithInt a i) = fmap WithInt (f a) <*> pure i

This is unsatisfying for two reasons:

1. The Traversable instance doesn't typecheck! Int# is of kind #, but pure
   expects an argument whose type is of kind *. This effectively prevents
   Traversable from being derived for any datatype with an unlifted argument
   type (#11174).

2. The generated code contains superfluous expressions. By the Monoid laws,
   we can reduce (f a <> mempty) to (f a), and by the Applicative laws, we can
   reduce (fmap WithInt (f a) <*> pure i) to (fmap (\b -> WithInt b i) (f a)).

We can fix both of these issues by incorporating a slight twist to the usual
algorithm that we use for -XDeriveFunctor. The differences can be summarized
as follows:

1. In the generated expression, we only fold over arguments whose types
   mention the last type parameter. Any other argument types will simply
   produce useless 'mempty's or 'pure's, so they can be safely ignored.

2. In the case of -XDeriveTraversable, instead of applying ConName,
   we apply (\b_i ... b_k -> ConName a_1 ... a_n), where

   * ConName has n arguments
   * {b_i, ..., b_k} is a subset of {a_1, ..., a_n} whose indices correspond
     to the arguments whose types mention the last type parameter. As a
     consequence, taking the difference of {a_1, ..., a_n} and
     {b_i, ..., b_k} yields the all the argument values of ConName whose types
     do not mention the last type parameter. Note that [i, ..., k] is a
     strictly increasing—but not necessarily consecutive—integer sequence.

     For example, the datatype

       data Foo a = Foo Int a Int a

     would generate the following Traversable instance:

       instance Traversable Foo where
         traverse f (Foo a1 a2 a3 a4) =
           fmap (\b2 b4 -> Foo a1 b2 a3 b4) (f a2) <*> f a4

Technically, this approach would also work for -XDeriveFunctor as well, but we
decide not to do so because:

1. There's not much benefit to generating, e.g., ((\b -> WithInt b i) (f a))
   instead of (WithInt (f a) i).

2. There would be certain datatypes for which the above strategy would
   generate Functor code that would fail to typecheck. For example:

     data Bar f a = Bar (forall f. Functor f => f a) deriving Functor

   With the conventional algorithm, it would generate something like:

     fmap f (Bar a) = Bar (fmap f a)

   which typechecks. But with the strategy mentioned above, it would generate:

     fmap f (Bar a) = (\b -> Bar b) (fmap f a)

   which does not typecheck, since GHC cannot unify the rank-2 type variables
   in the types of b and (fmap f a).

Note [Phantom types with Functor, Foldable, and Traversable]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Given a type F :: * -> * whose type argument has a phantom role, we can always
produce lawful Functor and Traversable instances using

    fmap _ = coerce
    traverse _ = pure . coerce

Indeed, these are equivalent to any *strictly lawful* instances one could
write, except that this definition of 'traverse' may be lazier.  That is, if
instances obey the laws under true equality (rather than up to some equivalence
relation), then they will be essentially equivalent to these. These definitions
are incredibly cheap, so we want to use them even if it means ignoring some
non-strictly-lawful instance in an embedded type.

Foldable has far fewer laws to work with, which leaves us unwelcome
freedom in implementing it. At a minimum, we would like to ensure that
a derived foldMap is always at least as good as foldMapDefault with a
derived traverse. To accomplish that, we must define

   foldMap _ _ = mempty

in these cases.

This may have different strictness properties from a standard derivation.
Consider

   data NotAList a = Nil | Cons (NotAList a) deriving Foldable

The usual deriving mechanism would produce

   foldMap _ Nil = mempty
   foldMap f (Cons x) = foldMap f x

which is strict in the entire spine of the NotAList.

Final point: why do we even care about such types? Users will rarely if ever
map, fold, or traverse over such things themselves, but other derived
instances may:

   data Hasn'tAList a = NotHere a (NotAList a) deriving Foldable

Note [EmptyDataDecls with Functor, Foldable, and Traversable]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

There are some slightly tricky decisions to make about how to handle
Functor, Foldable, and Traversable instances for types with no constructors.
For fmap, the two basic options are

   fmap _ _ = error "Sorry, no constructors"

or

   fmap _ z = case z of

In most cases, the latter is more helpful: if the thunk passed to fmap
throws an exception, we're generally going to be much more interested in
that exception than in the fact that there aren't any constructors.

In order to match the semantics for phantoms (see note above), we need to
be a bit careful about 'traverse'. The obvious definition would be

   traverse _ z = case z of

but this is stricter than the one for phantoms. We instead use

   traverse _ z = pure $ case z of

For foldMap, the obvious choices are

   foldMap _ _ = mempty

or

   foldMap _ z = case z of

We choose the first one to be consistent with what foldMapDefault does for
a derived Traversable instance.
-}