| Safe Haskell | Safe |
|---|---|
| Language | Haskell2010 |
Data.Generics.Fixplate
Description
This library provides Uniplate-style generic traversals and other recursion schemes for fixed-point types. There are many advantages of using fixed-point types instead of explicit recursion:
- we can easily add attributes to the nodes of an existing tree;
- there is no need for a custom type class, we can build everything on the top of
Functor,FoldableandTraversable, for which GHC can derive the instances for us; - we can provide interesting recursion schemes
- some operations can retain the structure of the tree, instead flattening it into a list;
- it is relatively straightforward to provide generic implementations of the zipper, tries, tree drawing, hashing, etc...
The main disadvantage is that it does not work well for mutually recursive data types, and that pattern matching becomes more tedious (but there are partial solutions for the latter).
Consider as an example the following simple expression language, encoded by a recursive algebraic data type:
data Expr = Kst Int | Var String | Add Expr Expr deriving (Eq,Show)
We can open up the recursion, and obtain a functor instead:
data Expr1 e = Kst Int | Var String | Add e e deriving (Eq,Show,Functor,Foldable,Traversable)
The fixed-point type Mu Expr1 is isomorphic to Expr.
However, we can also add some attributes to the nodes:
The type Attr Expr1 a = Mu (Ann Expr1 a) is the type of
with the same structure, but with each node having an extra
field of type a.
The functions in this library work on types like that: Mu f,
where f is a functor, and sometimes explicitely on Attr f a.
The organization of the modules (excluding Util.*) is the following:
- Data.Generics.Fixplate.Base - core types and type classes
- Data.Generics.Fixplate.Functor - sum and product functors
- Data.Generics.Fixplate.Traversals - Uniplate-style traversals
- Data.Generics.Fixplate.Morphisms - recursion schemes
- Data.Generics.Fixplate.Attributes - annotated trees
- Data.Generics.Fixplate.Open - functions operating on functors
- Data.Generics.Fixplate.Zipper - generic zipper
- Data.Generics.Fixplate.Draw - generic tree drawing (both ASCII and graphviz)
- Data.Generics.Fixplate.Pretty - pretty-printing of expression trees
- Data.Generics.Fixplate.Trie - generic generalized tries
- Data.Generics.Fixplate.Hash - annotating trees with their hashes
This module re-exports the most common functionality present in the library (but not for example the zipper, tries, hashing).
The library itself should be fully Haskell98 compatible; no language extensions are used. The only exception is the Data.Generics.Fixplate.Functor module, which uses the TypeOperators language extension for syntactic convenience (but this is not used anywhere else).
Note: to obtain Eq, Ord, Show, Read and other instances for
fixed point types like Mu Expr1, consult the documentation of the
EqF type class (cf. the related OrdF, ShowF and ReadF classes)
- module Data.Generics.Fixplate.Base
- module Data.Generics.Fixplate.Traversals
- module Data.Generics.Fixplate.Morphisms
- module Data.Generics.Fixplate.Attributes
- module Data.Generics.Fixplate.Draw
- class Functor f where
- class Foldable t where
- fold :: Monoid m => t m -> m
- foldMap :: Monoid m => (a -> m) -> t a -> m
- foldr :: (a -> b -> b) -> b -> t a -> b
- foldr' :: (a -> b -> b) -> b -> t a -> b
- foldl :: (b -> a -> b) -> b -> t a -> b
- foldl' :: (b -> a -> b) -> b -> t a -> b
- foldr1 :: (a -> a -> a) -> t a -> a
- foldl1 :: (a -> a -> a) -> t a -> a
- toList :: t a -> [a]
- null :: t a -> Bool
- length :: t a -> Int
- elem :: Eq a => a -> t a -> Bool
- maximum :: Ord a => t a -> a
- minimum :: Ord a => t a -> a
- sum :: Num a => t a -> a
- product :: Num a => t a -> a
- class (Functor t, Foldable t) => Traversable t where
- traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
- sequenceA :: Applicative f => t (f a) -> f (t a)
- mapM :: Monad m => (a -> m b) -> t a -> m (t b)
- sequence :: Monad m => t (m a) -> m (t a)
Documentation
module Data.Generics.Fixplate.Base
module Data.Generics.Fixplate.Draw
class Functor f where
The Functor class is used for types that can be mapped over.
Instances of Functor should satisfy the following laws:
fmap id == id fmap (f . g) == fmap f . fmap g
The instances of Functor for lists, Maybe and IO
satisfy these laws.
Minimal complete definition
Instances
| Functor [] | |
| Functor IO | |
| Functor Id | |
| Functor P | |
| Functor ZipList | |
| Functor ReadPrec | |
| Functor ReadP | |
| Functor Maybe | |
| Functor ((->) r) | |
| Functor (Either a) | |
| Functor ((,) a) | |
| Ix i => Functor (Array i) | |
| Functor (StateL s) | |
| Functor (StateR s) | |
| Functor (Const m) | |
| Monad m => Functor (WrappedMonad m) | |
| Arrow a => Functor (ArrowMonad a) | |
| Functor (Proxy *) | |
| Functor (Map k) | |
| Functor f => Functor (CoAttrib f) | |
| Functor f => Functor (Attrib f) | |
| Arrow a => Functor (WrappedArrow a b) | |
| Functor f => Functor (CoAnn f a) | |
| Functor f => Functor (Ann f a) | |
| (Functor f, Functor g) => Functor ((:*:) f g) | |
| (Functor f, Functor g) => Functor ((:+:) f g) | |
| Functor f => Functor (HashAnn hash f) |
class Foldable t where
Data structures that can be folded.
For example, given a data type
data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
a suitable instance would be
instance Foldable Tree where foldMap f Empty = mempty foldMap f (Leaf x) = f x foldMap f (Node l k r) = foldMap f l `mappend` f k `mappend` foldMap f r
This is suitable even for abstract types, as the monoid is assumed
to satisfy the monoid laws. Alternatively, one could define foldr:
instance Foldable Tree where foldr f z Empty = z foldr f z (Leaf x) = f x z foldr f z (Node l k r) = foldr f (f k (foldr f z r)) l
Foldable instances are expected to satisfy the following laws:
foldr f z t = appEndo (foldMap (Endo . f) t ) z
foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z
fold = foldMap id
sum, product, maximum, and minimum should all be essentially
equivalent to foldMap forms, such as
sum = getSum . foldMap Sum
but may be less defined.
If the type is also a Functor instance, it should satisfy
foldMap f = fold . fmap f
which implies that
foldMap f . fmap g = foldMap (f . g)
Methods
Combine the elements of a structure using a monoid.
foldMap :: Monoid m => (a -> m) -> t a -> m
Map each element of the structure to a monoid, and combine the results.
foldr :: (a -> b -> b) -> b -> t a -> b
foldr' :: (a -> b -> b) -> b -> t a -> b
Right-associative fold of a structure, but with strict application of the operator.
foldl :: (b -> a -> b) -> b -> t a -> b
foldl' :: (b -> a -> b) -> b -> t a -> b
Left-associative fold of a structure. but with strict application of the operator.
foldlf z =foldl'f z .toList
foldr1 :: (a -> a -> a) -> t a -> a
A variant of foldr that has no base case,
and thus may only be applied to non-empty structures.
foldr1f =foldr1f .toList
foldl1 :: (a -> a -> a) -> t a -> a
A variant of foldl that has no base case,
and thus may only be applied to non-empty structures.
foldl1f =foldl1f .toList
toList :: t a -> [a]
List of elements of a structure, from left to right.
Test whether the structure is empty. The default implementation is optimized for structures that are similar to cons-lists, because there is no general way to do better.
Returns the size/length of a finite structure as an Int. The
default implementation is optimized for structures that are similar to
cons-lists, because there is no general way to do better.
elem :: Eq a => a -> t a -> Bool infix 4
Does the element occur in the structure?
The largest element of a non-empty structure.
The least element of a non-empty structure.
The sum function computes the sum of the numbers of a structure.
The product function computes the product of the numbers of a
structure.
Instances
| Foldable [] | |
| Foldable Maybe | |
| Foldable (Either a) | |
| Foldable ((,) a) | |
| Ix i => Foldable (Array i) | |
| Foldable (Const m) | |
| Foldable (Proxy *) | |
| Foldable (Map k) | |
| Foldable f => Foldable (CoAttrib f) | |
| Foldable f => Foldable (Attrib f) | |
| Foldable f => Foldable (CoAnn f a) | |
| Foldable f => Foldable (Ann f a) | |
| (Foldable f, Foldable g) => Foldable ((:*:) f g) | |
| (Foldable f, Foldable g) => Foldable ((:+:) f g) | |
| Foldable f => Foldable (HashAnn hash f) |
class (Functor t, Foldable t) => Traversable t where
Functors representing data structures that can be traversed from left to right.
A definition of traverse must satisfy the following laws:
- naturality
t .for every applicative transformationtraversef =traverse(t . f)t- identity
traverseIdentity = Identity- composition
traverse(Compose .fmapg . f) = Compose .fmap(traverseg) .traversef
A definition of sequenceA must satisfy the following laws:
- naturality
t .for every applicative transformationsequenceA=sequenceA.fmaptt- identity
sequenceA.fmapIdentity = Identity- composition
sequenceA.fmapCompose = Compose .fmapsequenceA.sequenceA
where an applicative transformation is a function
t :: (Applicative f, Applicative g) => f a -> g a
preserving the Applicative operations, i.e.
and the identity functor Identity and composition of functors Compose
are defined as
newtype Identity a = Identity a
instance Functor Identity where
fmap f (Identity x) = Identity (f x)
instance Applicative Indentity where
pure x = Identity x
Identity f <*> Identity x = Identity (f x)
newtype Compose f g a = Compose (f (g a))
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)(The naturality law is implied by parametricity.)
Instances are similar to Functor, e.g. given a data type
data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
a suitable instance would be
instance Traversable Tree where traverse f Empty = pure Empty traverse f (Leaf x) = Leaf <$> f x traverse f (Node l k r) = Node <$> traverse f l <*> f k <*> traverse f r
This is suitable even for abstract types, as the laws for <*>
imply a form of associativity.
The superclass instances should satisfy the following:
- In the
Functorinstance,fmapshould be equivalent to traversal with the identity applicative functor (fmapDefault). - In the
Foldableinstance,foldMapshould be equivalent to traversal with a constant applicative functor (foldMapDefault).
Methods
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
Map each element of a structure to an action, evaluate these actions
from left to right, and collect the results. For a version that ignores
the results see traverse_.
sequenceA :: Applicative f => t (f a) -> f (t a)
Evaluate each action in the structure from left to right, and
and collect the results. For a version that ignores the results
see sequenceA_.
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
Map each element of a structure to a monadic action, evaluate
these actions from left to right, and collect the results. For
a version that ignores the results see mapM_.
sequence :: Monad m => t (m a) -> m (t a)
Evaluate each monadic action in the structure from left to
right, and collect the results. For a version that ignores the
results see sequence_.
Instances
| Traversable [] | |
| Traversable Maybe | |
| Traversable (Either a) | |
| Traversable ((,) a) | |
| Ix i => Traversable (Array i) | |
| Traversable (Const m) | |
| Traversable (Proxy *) | |
| Traversable (Map k) | |
| Traversable f => Traversable (CoAttrib f) | |
| Traversable f => Traversable (Attrib f) | |
| Traversable f => Traversable (CoAnn f a) | |
| Traversable f => Traversable (Ann f a) | |
| (Traversable f, Traversable g) => Traversable ((:*:) f g) | |
| (Traversable f, Traversable g) => Traversable ((:+:) f g) | |
| Traversable f => Traversable (HashAnn hash f) |