blob: 5fdba9d37b00a3a47329e76197aa5acb543a63d5 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::monoid::*;
/// Newtype wrapper for a ZipVec, a Vec whose monoid zips items together rather
/// than concatenating If we know how to combine elements of a Vec, then we can
/// combine two ZipVecs element-wise, padding the shortest with mzero.
///
/// e.g. using the addition monoid on ints:
///
/// > Zip(vec![0,1]).mappend( Zip(vec![1,2,4]) )
/// Zip( vec![1,3,4] )
pub struct Zip<T>(pub Vec<T>);
#[rustfmt::skip]
impl<T: Monoid> Semigroup for Zip<T> {
fn mappend(&self, b: &Zip<T>) -> Zip<T> {
let mut v = Zip(vec![]);
let mut a_ = self.0.iter();
let mut b_ = b.0.iter();
loop {
match (a_.next(), b_.next()) {
(Some(a), Some(b)) => v.0.push(a.mappend(b)),
(Some(a), None ) => v.0.push(a.mappend(&T::mzero())),
(None, Some(b)) => v.0.push(b.mappend(&T::mzero())),
(None, None ) => return v,
}
}
}
}
impl<T: Monoid> Monoid for Zip<T> {
fn mzero() -> Zip<T> {
Zip(vec![])
}
}
impl<T> Zip<T> {
pub fn map<U, F>(&self, f: F) -> Zip<U>
where
F: Fn(&T) -> U,
{
Zip(self.0.iter().map(f).collect())
}
}