我正在学习生锈(来自haskell背景)。 而且我正在努力使用多态类型-在haskell中,我将使用Holes / GHC类型推断来确定函数的返回类型被卡在rust中,以专门化泛型参数。
说我有一个描述Pomodoro会话的类型(我将这些数据存储在sqllite数据库中),并且我想在tui-table中显示这些数据
use tui::widgets::Row;
pub struct Pom {
pub id: i32,
pub duration: i64,
pub ticket_id: Option<String>,
pub note: Option<String>,
}
impl Pom {
pub fn as_row(self) -> ? {
let ret : [String; 4] = [
format!("{}", self.id),
format!("{}", self.duration),
self.ticket_id.unwrap_or(String::new()),
self.note.unwrap_or(String::new()),
];
Row::Data(ret.into_iter())
}
}
当我将?
替换为i32
(如{How do I print the type of a variable in Rust?中的建议)时,编译器非常有帮助,它告诉我它期望的类型为Row
。 / p>
我知道Row
是一个具有以下定义的枚举:
pub enum Row<D, I> where
D: Iterator<Item = I>,
I: Display, {
Data(D),
StyledData(D, Style),
}
我试图将不正确的类型插入专用类型签名中
pub fn as_row(self) -> Row<?,?> {
即再次,编译器告诉我?
不是迭代器,但是我不知道如何进一步专门化。
为了便于调查,请按以下步骤操作:
https://github.com/epsilonhalbe/pomodorust/tree/4f8c4929201ed90ddaef8af8d21076dbde78782b是指向github上可克隆和构建的项目的链接。我在这里发布的错误可以通过修改i32
来重现,以使编译失败
如果haskell中有等同于i32
的内容可以告诉我rust编译器推断的是哪种类型,那么我可以将文档中的示例拆开
src/database.rs
答案 0 :(得分:4)
@kopecs是正确的。 Row<std::slice::Iter<'a, String>, &'a String>
是正确的返回类型,但正如他们所解释的那样,由于它将返回对局部变量的引用,因此会导致生命周期问题。
tui::widgets::Row
要求其类型D
为Iterator
。使用数组和数组上的into_iter
的问题是IntoIterator
仅是"implemented for &[T; N] and &mut [T; N]",即引用。最好用this Reddit thread
任何此类需要将元素移出数组的实现都会在数组中留下漏洞,...如果在迭代过程中发生紧急情况,可能会导致发生坏事
...
我认为Vec在出现紧急情况时会通过泄漏内存来解决此问题
无论如何,解决此问题的一种方法是只使用Vec
而不是数组。然后,您的迭代器可以拥有字符串,而不是仅在原始数组中保留对字符串的引用。固定方法如下:
pub fn as_row(self) -> Row<impl Iterator<Item=String>, String> { // <-- correct return type
let ret = vec![ // <-- use a Vec
format!("{}", self.id),
format!("{}", self.duration),
self.ticket_id.unwrap_or(String::new()),
self.note.unwrap_or(String::new()),
];
Row::Data(ret.into_iter())
}