1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use im::vector::Vector;
use crate::Layer::*;

#[derive(Clone, Debug)]
pub enum Layer<'a, T: 'static + Applicable + Clone> {
    X(T),
    LL(&'a [Layer<'a, T>]),
    //    Juxt(&'a [Layer<'a, T>]),
    Map(& 'a Layer<'a, T>),
    _Map {child: & 'a Layer<'a, T>,
        accum: Vector<T::Item>,
        remaining: Vector<T::Item>},
//    Reduce(& 'static Flap<T>)
//    XZip(Rc<&'static [Flap<T>]>),
//    Cond(Rc<&'static [Flap<T>]>),
}

impl<'a, TImpl: 'static + Applicable + Clone> Layer<'a, TImpl> {
    pub fn solvestep(self, input: TImpl::Item) -> Flapp<'a, TImpl> {
        match self {
            X(f) => Flapp { stack: None, input: f.apply(input) },
            LL(layers) => Flapp {stack: Some(Vector::from(layers)), input},
            Map(child) => {
                let mut input_seq = input.seq();
                if let Some(next_input) = input_seq.pop_front() {
                    let mut cont = Vector::unit(_Map { child, accum: Vector::new(), remaining: input_seq });
                    cont.push_front(child.clone());
                    Flapp {stack: Some(cont), input: next_input}
                } else {
                    Flapp {stack: None, input: TImpl::Item::item(input_seq)}
                }
            },
            _Map {child, mut accum, mut remaining} => {
//                let mut input_seq = input.seq();
                accum.push_back(input);
                if let Some(next_input) = remaining.pop_front() {
                    let mut cont = Vector::unit(_Map { child, accum, remaining });
                    cont.push_front(child.clone());
                    Flapp {stack: Some(cont), input: next_input}
                } else {
                    Flapp{stack: None, input: TImpl::Item::item(accum)}
                }
            }
//            , _ => panic!("unhappy path :(")
        }
    }

    pub fn solve(self, input: TImpl::Item) -> TImpl::Item
    {
        let mut stack = Vector::unit(self);
        let mut output = input;
        while let Some(next_step) = stack.pop_front() {
            let Flapp{stack: additional_stack, input: new_output} = next_step.solvestep(output);
            output = new_output;
            if let Some(mut new_stack) = additional_stack {
                new_stack.append(stack);
                stack = new_stack;
            }
        }
        output
    }
}

pub trait Applicable {
    type Item: Clone + AsSeq<Self::Item>;
    fn apply(self, input: Self::Item) -> Self::Item;
}

pub struct Flapp<'a, TImpl: 'static + Applicable + Clone> {stack: Option<Vector<Layer<'a, TImpl>>>, input: TImpl::Item}

pub trait AsSeq<T> {
    fn seq(self) -> Vector<T>;
    fn item(accum: Vector<T>) -> T;
}