在Rust的树折

时间:2014-07-01 06:17:31

标签: rust

我正在尝试在生锈中实施tree fold。我的first attempt按预期编译并运行。

pub enum Tree<T> {
    Leaf,
    Node(Box<Tree<T>>, T, Box<Tree<T>>)
}

impl<T, U: Copy> Tree<T> {
    fn fold(self, f: |l: U, x: T, r: U| -> U, acc: U) -> U {
        match self {
            Leaf => acc,
            Node(box l, x, box r) => {
                let l = l.fold(|l,x,r| {f(l,x,r)}, acc);
                let r = r.fold(|l,x,r| {f(l,x,r)}, acc);
                f(l, x, r)
            }
        }
    }
}

fn main() {
    let tl = Node(box Leaf, 1i, box Leaf);
    let tr = Node(box Leaf, 2i, box Leaf);
    let t  = Node(box tl, 3i, box tr);

    println!("size(t) == {}", t.fold(|l,_,r|{l + 1i + r}, 0))
}

但是,当我尝试将size impl移到pub enum Tree<T> { Leaf, Node(Box<Tree<T>>, T, Box<Tree<T>>) } impl<T, U: Copy> Tree<T> { fn fold(self, f: |l: U, x: T, r: U| -> U, acc: U) -> U { match self { Leaf => acc, Node(box l, x, box r) => { let l = l.fold(|l,x,r| {f(l,x,r)}, acc); let r = r.fold(|l,x,r| {f(l,x,r)}, acc); f(l, x, r) } } } fn size(self) -> uint { self.fold(|l, _, r| {l + 1u + r}, 0u) } } fn main() { let tl = Node(box Leaf, 1i, box Leaf); let tr = Node(box Leaf, 2i, box Leaf); let t = Node(box tl, 3i, box tr); println!("size(t) == {}", t.size()) } 块中以使其成为方法时:

<anon>:28:31: 28:39 error: cannot determine a type for this expression: unconstrained type
<anon>:28     println!("size(t) == {}", t.size())
                                    ^~~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
<anon>:28:5: 29:2 note: expansion site
error: aborting due to previous error
playpen: application terminated with error code 101
Program ended.

我在防锈围栏中收到以下错误。

{{1}}

我希望有人能说清楚我做错了什么,以及如何解决它。

1 个答案:

答案 0 :(得分:4)

你的两件事之间存在着重要的区别。

首先,你有这个:

t.fold(|l,x,r|{l + x + r}, 0)

在第二个中,你有这个(显示self更改为t):

t.fold(|l, x, r| {l + 1 + r}, 0)

看到区别? l + 1 + r不是l + x + r

(从那时起,所有案例的大小都变为l + 1 + r,而不是l + x + r,总和。)

完成此操作后,您会遇到问题,因为uint不是int。您需要整理TU。基本上,您希望lxr0都属于同一类型,即之前的T。这需要对T

进一步限制
  • 必须Copy,才能满足U

  • 您必须能够T添加T并获得T。这是std::num::Add<T, T>

  • 您必须能够获得T类型的零。这是std::num::Zero特征和Zero::zero()方法。

  • 您必须能够获得T类型的一个。这是std::num::One特征和One::one()方法。

虽然我们处于此状态,但U可能应该是fold函数的泛型,而不是impl块,但要么会这样做。

最后,我们最终得到了functioning code

use std::num::Zero;

pub enum Tree<T> {
    Leaf,
    Node(Box<Tree<T>>, T, Box<Tree<T>>)
}

impl<T> Tree<T> {
    fn fold<U: Copy>(self, f: |l: U, x: T, r: U| -> U, acc: U) -> U {
        match self {
            Leaf => acc,
            Node(box l, x, box r) => {
                let l = l.fold(|l, x, r| f(l, x, r), acc);
                let r = r.fold(|l, x, r| f(l, x, r), acc);
                f(l, x, r)
            }
        }
    }
}

impl<T: Copy + Add<T, T> + Zero + One> Tree<T> {
    fn size(self) -> T {
        self.fold(|l: T, _: T, r: T| l + One::one() + r, Zero::zero())
    }
}

fn main() {
    let tl = Node(box Leaf, 1i, box Leaf);
    let tr = Node(box Leaf, 2i, box Leaf);
    let t = Node(box tl, 3i, box tr);

    println!("size(t) == {}", t.size())
}

(注意封闭内容周围的花括号也不是必需的。)