stock-0.1.0.0: Stock-style deriving via coercion, with no Generic
Safe HaskellNone
LanguageGHC2021

Stock.Bifunctor

Description

All Stock2 synthesizers (classes over a two-parameter type P):

  • Bifunctor / Bifoldable — map/fold the last two parameters.
  • Eq2 / Ord2 / Show2 / Read2 — the lifted "two-parameter" Classes (mirroring Stock.Classes1 one level up).
  • Bitraversable — synthesized directly (usable at the wrapper / via the one-liner; a bare deriving via can't, abstract-applicative role).
  • Category — pointwise id/(.) for a single-constructor product whose fields are each a Category in the two params.

Field shapes: each of the two parameters, constants, or a (covariant) functor applied to one (the flat classifyBiField); Bifunctor also goes through the n-ary variance engine for nested/self-applied fields like Either a b.

Synopsis

Documentation

data BiField Source #

Constructors

BFA 
BFB

the field is a resp. b

BFConst

mentions neither

BFFoldA Type 
BFFoldB Type

h a / h b (covariant, h over one param)

classifyCatField :: TyVar -> TyVar -> Type -> Maybe Type Source #

For Category: a field must be exactly h a b — a (poly-kinded) two-parameter constructor h applied to both datatype parameters, in order. h is the per-field Category (e.g. (->), (:~:), Kleisli m, or a Basic m from an Override). Returns h (which must not mention the parameters). Constants and one-parameter shapes have no id/(.), so they yield Nothing and the whole synthesis bails.

data CatFld Source #

How one field of a Category product is handled: it is a Category h (with a realFt(t1,t2) ~R h t1 t2 coercion builder — Refl unless reshaped by an Override2), or a constant m handled Const-style via its Monoid (id = mempty, (.) = (<>)) — the automatic, Basic-free version.

Constructors

CatF Type (Type -> Type -> Coercion) 
MonF Type 

synthCategory :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Category (Stock2 P) for a single-constructor product whose every field is a Category in the two parameters (shape h a b). id and (.) are pointwise — id = P id .. id, P g.. . P h.. = P (g.h).. — exactly the Semigroup pattern lifted to two parameters. Category is poly-kinded (cat :: k -> k -> Type), so the kind k (here always Type) is threaded through the dictionary and through every id/(.) at the field categories.

P may be wrapped in Override2 cfg P: then each positional modifier m reshapes its field to m a b (the modifier applied to both parameters), with a per-field realFt ~R m a b coercion, so fields that are not yet categories (an Int, an a -> Maybe b) become ones (Basic (Sum Int), Kleisli Maybe).

safeIdx :: [a] -> Int -> Maybe a Source #

Total list indexing.

synthBifoldable :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Bifoldable (Stock2 P). bifoldMap maps a-fields with the first function, b-fields with the second, folds h a/h b fields with h's own foldMap, drops constants, and combines with (<>); all other methods come from the class defaults. No superclass (unlike Bifunctor).

synthBitraversable :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Bitraversable (Stock2 P), directly (not by coercion — like Traversable, bitraverse's result f (t c d) puts the wrapper under an abstract applicative, so DerivingVia can't coerce it onto P; the instance is usable at Stock2 P / via the one-liner). Per constructor, pure mkCon <*> f1 <*> …: an a/b field uses the supplied function, a constant uses pure, and an h a/h b field uses traverse @h (an Override2-reshaped functor goes through the modifier, re-wrapped with pure coerce <*> _). Bifunctor and Bifoldable superclasses come from their own synthesizers.

synthBifunctor :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Bifunctor (Stock2 P). bimap maps a-fields with the first function and b-fields with the second; first/second come from the class defaults. Bifunctor has a quantified superclass forall a. Functor (p a), which we supply by synthesizing the Functor (Stock2 P a) dictionary under a type-lambda (the Functor maps the second parameter).

zipLiftBi :: TyCon -> [Type] -> (Type -> Type -> Coercion) -> (Type, Type) -> (Type, Type) -> Type -> Id -> Id -> (Int -> Int -> CoreExpr) -> ([CoreExpr] -> TcPluginM CoreExpr) -> (Int -> Type -> Id -> Id -> TcPluginM (Maybe (CoreExpr, [Ct]))) -> TcPluginM (Maybe (CoreExpr, [Ct])) Source #

A fresh kind-Type type variable (for the forall a b in fmap).

The Stock2 counterpart of zipLift2: walk two values of the same Stock2 P shape (fa :: P a c, fb :: P b d) in lock-step, combining the per-field-pair results of matching constructors. Shared by liftEq2 (short-circuit conjunction) and liftCompare2 (lexicographic).

stock2Supers :: Class -> Type -> CtLoc -> TcPluginM ([CoreExpr], [Ct]) Source #

The superclass evidence for C2 (Stock2 P): each entry of C2's classSCTheta instantiated at the via-target and requested as a wanted (discharged by the plugin: lifted built-ins, or the Stock2 passthrough).

synthEq2 :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Eq2 (Stock2 P): liftEq2 is same-constructor-and-all-fields, with a-fields compared by the first function, b-fields by the second, h a/h b fields by liftEq, constants by (==). Override2 is transparent for Eq2: a hashing/forcing modifier does not change structural equality, so peel the wrapper and compare the real fields. (This makes deriving Hashable2 via Overriding2 … work: its Eq2 superclass is dragged through the same config.)

synthOrd2 :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Ord2 (Stock2 P): liftCompare2 orders by constructor tag, then lexicographically by fields (first-param fields by the first function, second by the second, h a/h b by liftCompare, constants by compare).

synthShow2 :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Show2 (Stock2 P): liftShowsPrec2 renders like derived Show (prefix infix record, precedence-parenthesised) but shows a first-param field with spA, a second with spB, an h a/h b field with liftShowsPrec, a constant with its own showsPrec.

synthRead2 :: GenEnv -> Class -> CtLoc -> Type -> Type -> TcPluginM (Maybe (EvTerm, [Ct])) Source #

Synthesize Read2 (Stock2 P): liftReadsPrec2 parses like derived Read (prefix infix record, precedence-aware) but reads a first-param field with rp1, a second with rp2, an h a/h b field with liftReadsPrec, a constant with its own readsPrec. The bivariate counterpart of synthRead1; quantified superclasses come via stock2Supers.