Personal tools

Diagrams/Dev/Fixpoint

From HaskellWiki

< Diagrams | Dev(Difference between revisions)
Jump to: navigation, search
(Some work on detailed design for fixpoint semantics)
(more design for fixpoint implementation)
Line 44: Line 44:
 
type QDiagram b v m = Contextual b v m (RTree b v Annotation, Summary b v m)
 
type QDiagram b v m = Contextual b v m (RTree b v Annotation, Summary b v m)
   
It's important that this is NOT a newtype, so we can freely use the <code>Monad</code> instance for <code>Contextual</code> when working with diagrams.
+
It's important that this is NOT a newtype, so we can freely use the <code>Monad</code> instance for <code>Contextual</code> when working with diagrams. This also means we don't need <code>Wrapped</code> or <code>Rewrapped</code> instances for it anymore.
  +
  +
* The implementation of <code>applyAnnotation</code> needs to change. All it needs to do is create a new <code>RTree</code> node (an <code>RAnnot</code> node), ignoring the context and having no effect on the summary. So something like
  +
  +
applyAnnotation an = fmap (first (Node (RAnnot an) . (:[])))
  +
  +
We may end up having to do similar things in other situations so it may make sense to factor out parts of this into general utilities (e.g. <code>addRoot :: RNode -> RTree -> RTree</code> etc.)
  +
  +
* Of course the implementation of almost all the rest of the functions in this module will need to change as well. I'll walk through a few particular examples and then discuss more general principles. First, <code>pointDiagram</code>. The current code is
  +
  +
pointDiagram :: (Fractional (Scalar v), InnerSpace v)
  +
=> Point v -> QDiagram b v m
  +
pointDiagram p = QD $ D.leafU (inj . toDeletable $ pointEnvelope p)
  +
  +
This creates a point envelope, wraps it in <code>Deletable</code>, injects it into an <code>UpAnnots</code> value, and uses it to create a leaf <code>DUALTree</code>. Everything up through <code>UpAnnots</code> still applies (though the name of <code>UpAnnots</code> has changed). What's different is that we aren't creating an explicit tree with summary values at leaves; we simply return the summary value as part of the result of the diagram function. So we can create a function <code>leafS</code> in parallel with <code>leafU</code>:
  +
  +
emptyTree = Node REmpty []
  +
  +
leafS :: Summary b v m -> QDiagram b v m
  +
leafS s = return (emptyTree, s)
  +
  +
Then the implementation of <code>pointDiagram</code> only needs to change to
  +
  +
pointDiagram p = leafS (inj . toDeletable $ pointEnvelope p)
   
 
==== <code>Diagrams.Core.Types</code> ====
 
==== <code>Diagrams.Core.Types</code> ====

Revision as of 21:00, 17 May 2014

This page describes the motivation and design for a refactoring of diagrams, to give them a semantics based on computing fixed points of functions from "context" information to raw tree of primitives together with some summary information.

Contents

1 Reference

See the original "manifesto" and ensuing mailing list discussion here: http://thread.gmane.org/gmane.comp.lang.haskell.diagrams/383

See also later IRC discussion beginning here: http://ircbrowse.net/browse/diagrams?events_page=935

2 Detailed design

Most of the changes should be in the diagrams-core package, though a few things in diagrams-lib may need to change as well.

2.1 diagrams-core

No changes should be necessary to the following modules (all prefixed by Diagrams.Core): Envelope, HasOrigin, Juxtapose, Names, Points, Query, Trace, Transform, V.

I'm not sure about Style yet.

2.1.1 Diagrams.Core.Compile

  • Change the name of UpAnnots to Summary.
  • Change the name of DownAnnots to Context, and change its definition to
 type Context b v m = Style v
                    ::: Name
                    ::: SubMap b v m
                    ::: ()

The addition of SubMap is so that we can use the positions of laid-out subdiagrams to compute the positions of others.

  • transfToAnnot and transfFromAnnot can be deleted.
  • QDiaLeaf and withQDiaLeaf can be deleted.
  • Create new definitions
 type ContextualT b v q m a = ReaderT (Context b v q) m a
 type Contextual b v q a = ContextualT b v q Identity a

One could imagine making ContextualT a newtype but that would necessitate writing lots of instances for things like MonadState, MonadReader, and so on.

  • The definition of QDiagram should be changed to something like
 type QDiagram b v m = Contextual b v m (RTree b v Annotation, Summary b v m) 

It's important that this is NOT a newtype, so we can freely use the Monad instance for Contextual when working with diagrams. This also means we don't need Wrapped or Rewrapped instances for it anymore.

  • The implementation of applyAnnotation needs to change. All it needs to do is create a new RTree node (an RAnnot node), ignoring the context and having no effect on the summary. So something like
 applyAnnotation an = fmap (first (Node (RAnnot an) . (:[])))

We may end up having to do similar things in other situations so it may make sense to factor out parts of this into general utilities (e.g. addRoot :: RNode -> RTree -> RTree etc.)

  • Of course the implementation of almost all the rest of the functions in this module will need to change as well. I'll walk through a few particular examples and then discuss more general principles. First, pointDiagram. The current code is
 pointDiagram :: (Fractional (Scalar v), InnerSpace v)
              => Point v -> QDiagram b v m
 pointDiagram p = QD $ D.leafU (inj . toDeletable $ pointEnvelope p)

This creates a point envelope, wraps it in Deletable, injects it into an UpAnnots value, and uses it to create a leaf DUALTree. Everything up through UpAnnots still applies (though the name of UpAnnots has changed). What's different is that we aren't creating an explicit tree with summary values at leaves; we simply return the summary value as part of the result of the diagram function. So we can create a function leafS in parallel with leafU:

 emptyTree = Node REmpty []
 leafS :: Summary b v m -> QDiagram b v m
 leafS s = return (emptyTree, s)

Then the implementation of pointDiagram only needs to change to

 pointDiagram p = leafS (inj . toDeletable $ pointEnvelope p)

2.1.2 Diagrams.Core.Types

2.2 diagrams-lib