public TrainingStatistics merge(TrainingStatistics other) {
   Map<SentenceKey, EnsembleStatistics> newStats = new HashMap<>();
   // Add elements from this statistics
   for (Map<SentenceKey, EnsembleStatistics> map : this.impl) {
     for (SentenceKey key : map.keySet()) {
       newStats.put(key, new EnsembleStatistics(map.get(key)));
     }
   }
   // Add elements from other statistics
   for (Map<SentenceKey, EnsembleStatistics> map : other.impl) {
     for (SentenceKey key : map.keySet()) {
       EnsembleStatistics existing = newStats.get(key);
       if (existing == null) {
         existing = new EnsembleStatistics(new LinkedList<SentenceStatistics>());
         newStats.put(key, existing);
       }
       existing.addInPlace(map.get(key));
     }
   }
   // Return
   return new TrainingStatistics(Maybe.Just(newStats));
 }
 public SentenceStatistics(Counter<String> relationDistribution) {
   this.confidence = Maybe.Nothing();
   this.relationDistribution = relationDistribution;
 }
 // note that these constructors expect standard probabilities
 public SentenceStatistics(Counter<String> relationDistribution, double confidence) {
   this.confidence = Maybe.Just(confidence);
   this.relationDistribution = relationDistribution;
 }
 public static TrainingStatistics undefined() {
   return new TrainingStatistics(Maybe.<Map<SentenceKey, EnsembleStatistics>>Nothing());
 }
 public static TrainingStatistics empty() {
   return new TrainingStatistics(Maybe.Just(new HashMap<SentenceKey, EnsembleStatistics>()));
 }
 public Maybe<Set<SentenceKey>> getSentenceKeys() {
   if (!impl.isDefined()) return Maybe.Nothing();
   return Maybe.Just(impl.get().keySet());
 }