| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Control.Monad.Free.Foil.Annotated
Description
Annotating every node of a free foil term.
A node can be annotated with anything: a source position, a type, a memoised
normal form. AnnSig turns a signature into an annotated one, and
AnnAST is the annotated syntax it generates.
The annotation is a functor of the term, and that is what lets it depend on
the node's scope. In the signature's term parameter is
the AST at the node's own scope, so an annotation built from it holds terms in
that scope — which is what a type annotation in a dependent language needs.
An annotation that ignores the term (a source position, say) is AST binder sig n.Const a
Whether two annotations must agree for their nodes to match is a property of
ann, not of AnnSig. Two examples, and they are the two you will want:
An annotation that ignores the term (a source position) and is compared:
instance Eq a => ZipMatchK (Const (a :: Type)) where
zipMatchWithK _ (Const l) (Const r)
| l == r = Just (Const l)
| otherwise = NothingAn annotation that holds terms (a type, say) and is ignored, so that two terms differing only in their types are α-equivalent. Make the held term optional, so that pairing can fail without failing the match:
newtype TypeOf term = TypeOf (Maybe term)
instance ZipMatchK TypeOf where
zipMatchWithK (f :^: M0) (TypeOf l) (TypeOf r) =
Just (TypeOf (do { a <- l; b <- r; f a b }))The instance must return Just unconditionally, and lazily. Matching is
annotation-blind, so it must succeed whatever the annotations are; the paired
annotation is a thunk the (annotation-skipping) Bifoldable never forces. A
strict shape — TypeOf , or anything that yields <$> f l rNothing when
f fails — is a footgun twice over: it breaks blindness (two nodes with
different types would fail to match), and it diverges for a finite or
lazily-bottomed annotation (a universe tower ending in error, say), because
forcing the annotation runs off the end. This is why the held term is a Maybe:
a plain term field would have no value to pair when f fails, forcing a
bottom into the result.
Do not reach for the generic instance here. It compares the annotation's
shape, so a node carrying a memoised normal form would fail to match the same
node without one. (Nor is zipMatchViaChooseLeft available: an annotation
holding terms must construct a value at the result index, and cannot simply
pick a side.)
Note the asymmetry in the instances below: Bifunctor and Bitraversable
traverse the annotation, but Bifoldable does not. This is deliberate — see
AnnSig.
Synopsis
- data AnnSig (ann :: Type -> Type) (sig :: Type -> Type -> Type) scope term = AnnSig (ann term) (sig scope term)
- type AnnAST (binder :: S -> S -> Type) (ann :: Type -> Type) (sig :: Type -> Type -> Type) = AST binder (AnnSig ann sig)
- type AnnScopedAST (binder :: S -> S -> Type) (ann :: Type -> Type) (sig :: Type -> Type -> Type) = ScopedAST binder (AnnSig ann sig)
- pattern AnnNode :: ann (AnnAST binder ann sig n) -> sig (AnnScopedAST binder ann sig n) (AnnAST binder ann sig n) -> AnnAST binder ann sig n
- annotationOf :: forall (binder :: S -> S -> Type) ann (sig :: Type -> Type -> Type) (n :: S). AnnAST binder ann sig n -> Maybe (ann (AnnAST binder ann sig n))
- freeVarsOfAnnotated :: forall (n :: S) (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (ann :: Type -> Type). (Distinct n, CoSinkable binder, Bifoldable sig, Foldable ann) => AnnAST binder ann sig n -> [Name n]
Documentation
data AnnSig (ann :: Type -> Type) (sig :: Type -> Type -> Type) scope term Source #
A signature, with every node annotated by an ann built from the node's term.
The annotation is applied to the term parameter, so in an
it holds terms in the node's own scope.AST binder (AnnSig ann sig) n
Bifoldable deliberately skips the annotation. That is what makes
α-equivalence annotation-blind: alphaEquiv consumes a
zipped node with bifoldMap, so a type annotation is never compared, and two
terms that differ only in their annotations are α-equivalent. The price is that
freeVarsOf, which is also Bifoldable, does not see
variables occurring inside annotations. Use freeVarsOfAnnotated when those
matter.
Constructors
| AnnSig (ann term) (sig scope term) |
Instances
| Bifoldable sig => Bifoldable (AnnSig ann sig) Source # | The annotation is not folded. See | ||||
Defined in Control.Monad.Free.Foil.Annotated | |||||
| (Functor ann, Bifunctor sig) => Bifunctor (AnnSig ann sig) Source # | |||||
| (Traversable ann, Bitraversable sig) => Bitraversable (AnnSig ann sig) Source # | |||||
Defined in Control.Monad.Free.Foil.Annotated Methods bitraverse :: Applicative f => (a -> f c) -> (b -> f d) -> AnnSig ann sig a b -> f (AnnSig ann sig c d) # | |||||
| (ZipMatchK ann, ZipMatchK sig) => ZipMatchK (AnnSig ann sig :: Type -> Type -> Type) Source # | Matching for The generic default would rebuild the Generics.Kind view of every node on
every comparison, and comparing terms is most of what a typechecker does, so
for an annotated signature — where it lands on the hottest path — that is a
measurable cost. | ||||
| GenericK (AnnSig ann sig :: Type -> Type -> Type) Source # | |||||
| (Foldable ann, Foldable (sig scope)) => Foldable (AnnSig ann sig scope) Source # | |||||
Defined in Control.Monad.Free.Foil.Annotated Methods fold :: Monoid m => AnnSig ann sig scope m -> m # foldMap :: Monoid m => (a -> m) -> AnnSig ann sig scope a -> m # foldMap' :: Monoid m => (a -> m) -> AnnSig ann sig scope a -> m # foldr :: (a -> b -> b) -> b -> AnnSig ann sig scope a -> b # foldr' :: (a -> b -> b) -> b -> AnnSig ann sig scope a -> b # foldl :: (b -> a -> b) -> b -> AnnSig ann sig scope a -> b # foldl' :: (b -> a -> b) -> b -> AnnSig ann sig scope a -> b # foldr1 :: (a -> a -> a) -> AnnSig ann sig scope a -> a # foldl1 :: (a -> a -> a) -> AnnSig ann sig scope a -> a # toList :: AnnSig ann sig scope a -> [a] # null :: AnnSig ann sig scope a -> Bool # length :: AnnSig ann sig scope a -> Int # elem :: Eq a => a -> AnnSig ann sig scope a -> Bool # maximum :: Ord a => AnnSig ann sig scope a -> a # minimum :: Ord a => AnnSig ann sig scope a -> a # | |||||
| (Traversable ann, Traversable (sig scope)) => Traversable (AnnSig ann sig scope) Source # | |||||
Defined in Control.Monad.Free.Foil.Annotated Methods traverse :: Applicative f => (a -> f b) -> AnnSig ann sig scope a -> f (AnnSig ann sig scope b) # sequenceA :: Applicative f => AnnSig ann sig scope (f a) -> f (AnnSig ann sig scope a) # mapM :: Monad m => (a -> m b) -> AnnSig ann sig scope a -> m (AnnSig ann sig scope b) # sequence :: Monad m => AnnSig ann sig scope (m a) -> m (AnnSig ann sig scope a) # | |||||
| (Functor ann, Functor (sig scope)) => Functor (AnnSig ann sig scope) Source # | |||||
| Generic (AnnSig ann sig scope term) Source # | |||||
Defined in Control.Monad.Free.Foil.Annotated Associated Types
| |||||
| type RepK (AnnSig ann sig :: Type -> Type -> Type) Source # | |||||
| type Rep (AnnSig ann sig scope term) Source # | |||||
Defined in Control.Monad.Free.Foil.Annotated type Rep (AnnSig ann sig scope term) = D1 ('MetaData "AnnSig" "Control.Monad.Free.Foil.Annotated" "free-foil-0.3.2-Ined4vrrcdxBXWLRXM9Um9" 'False) (C1 ('MetaCons "AnnSig" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (ann term)) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (sig scope term)))) | |||||
type AnnAST (binder :: S -> S -> Type) (ann :: Type -> Type) (sig :: Type -> Type -> Type) = AST binder (AnnSig ann sig) Source #
An annotated scope-safe term.
type AnnScopedAST (binder :: S -> S -> Type) (ann :: Type -> Type) (sig :: Type -> Type -> Type) = ScopedAST binder (AnnSig ann sig) Source #
An annotated scope-safe term under a binder.
pattern AnnNode :: ann (AnnAST binder ann sig n) -> sig (AnnScopedAST binder ann sig n) (AnnAST binder ann sig n) -> AnnAST binder ann sig n Source #
An annotated node.
annotationOf :: forall (binder :: S -> S -> Type) ann (sig :: Type -> Type -> Type) (n :: S). AnnAST binder ann sig n -> Maybe (ann (AnnAST binder ann sig n)) Source #
The annotation of a term, unless it is a variable (which is not a node, so it carries none).
freeVarsOfAnnotated :: forall (n :: S) (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (ann :: Type -> Type). (Distinct n, CoSinkable binder, Bifoldable sig, Foldable ann) => AnnAST binder ann sig n -> [Name n] Source #
The free variables of an annotated term, including those occurring inside annotations.
freeVarsOf misses the latter, since Bifoldable skips
the annotation (see AnnSig).