001    package fj.data.fingertrees;
002    
003    import fj.pre.Monoid;
004    import fj.F;
005    
006    /**
007     * Determines how the elements of a tree are measured and how measures are summed. Consists of a monoid and a
008     * measuring function. Different instances of this class will result in different behaviours for the tree.
009     */
010    public final class Measured<V, A> {
011      private final Monoid<V> m;
012      private final F<A, V> measure;
013    
014      private Measured(final Monoid<V> m, final F<A, V> measure) {
015        this.m = m;
016        this.measure = measure;
017      }
018    
019      public static <V, A> Measured<V, A> measured(final Monoid<V> m, final F<A, V> measure) {
020        return new Measured<V, A>(m, measure);
021      }
022    
023      /**
024       * Returns the monoid used to sum measures.
025       *
026       * @return the monoid used to sum measures.
027       */
028      public Monoid<V> monoid() {
029        return m;
030      }
031    
032      /**
033       * Returns the measuring function.
034       *
035       * @return the measuring function.
036       */
037      public F<A, V> measure() {
038        return measure;
039      }
040    
041      /**
042       * Measures a given element.
043       *
044       * @param a An element to measure.
045       * @return the element's measurement.
046       */
047      public V measure(final A a) {
048        return measure.f(a);
049      }
050    
051      /**
052       * Sums the given measurements with the monoid.
053       *
054       * @param a A measurement to add to another.
055       * @param b A measurement to add to another.
056       * @return The sum of the two measurements.
057       */
058      public V sum(final V a, final V b) {
059        return m.sum(a, b);
060      }
061    
062      /**
063       * Returns the identity measurement for the monoid.
064       *
065       * @return the identity measurement for the monoid.
066       */
067      public V zero() {
068        return m.zero();
069      }
070    
071      /**
072       * A measured instance for nodes.
073       *
074       * @return A measured instance for nodes.
075       */
076      public Measured<V, Node<V, A>> nodeMeasured() {
077        return new Measured<V, Node<V, A>>(m, new F<Node<V, A>, V>() {
078          public V f(final Node<V, A> node) {
079            return node.measure();
080          }
081        });
082      }
083    
084      /**
085       * A measured instance for digits.
086       *
087       * @return A measured instance for digits.
088       */
089      public Measured<V, Digit<V, A>> digitMeasured() {
090        return new Measured<V, Digit<V, A>>(m, new F<Digit<V, A>, V>() {
091          public V f(final Digit<V, A> d) {
092            return d.measure();
093          }
094        });
095      }
096    
097    }