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
#[derive (Debug, PartialEq, Eq)]
pub enum Fix<A> {
    Pro(A),
    Fix(A)
}

impl<A> Fix<A> {
    pub fn map<B, F: FnOnce(A) -> B>(self, f: F) -> Fix<B> {
        match self {
            Fix::Pro(a) => Fix::Pro(f(a)),
            Fix::Fix(a) => Fix::Fix(f(a))
        }
    }
}

pub fn compose<A, F, G>(a: A, mut f: F, mut g: G) -> Fix<A>
    where F: FnMut(A) -> Fix<A>, G: FnMut(A) -> Fix<A> {
    match f(a) {
        Fix::Fix(b) => g(b),
        fix => fix
    }
}

pub fn fix<A, F: FnMut(A) -> Fix<A>>(mut a: A, mut f: F) -> A {
    loop {
        match f(a) {
            Fix::Fix(b) => return b,
            Fix::Pro(b) => a = b
        }
    }
}

pub fn fix_result<A, E, F: FnMut(A) -> Result<Fix<A>, E>>(mut a: A, mut f: F) -> Result<A, E> {
    loop {
        match f(a) {
            Result::Err(err) => return Result::Err(err),
            Result::Ok(Fix::Fix(b)) => return Result::Ok(b),
            Result::Ok(Fix::Pro(b)) => a = b
        }
    }
}