簡體   English   中英

如何使用Rust枚舉,結構,特征或其他任何東西來構造包含存在類型的值?

[英]How can I use a Rust enum, struct, trait or anything else to construct a value containing an existential type?

什么Rust構造可以大致完成與以下OCaml相同的任務?

type t = F : 'x * ('x -> string) -> t

let int_eg = F(1, string_of_int)
let str_eg = F("foo", fun x -> x)

let print x = print_string (match x with
  | F(x,to_str) -> to_str x)

與存在性類型最接近的是特征對象:

// how ToString is declared
trait ToString {
    fn to_string(&self) -> String;
}

let i32_str: Box<ToString> = Box::new(1);
let str_str: Box<ToString> = Box::new("foo");

fn print(value: &ToString) -> String {
    value.to_string()
}
print_x(&i32_str);  // automatically coerced from Box<ToString> to &ToString
print_x(&str_str);

對於特征對象,實際類型將被刪除,唯一剩下的就是知道該特定值是實現給定特征的某種類型。 它與Haskell中具有類型類邊界的存在類型非常相似:

data Showable = Showable (forall a. Show a => a)

沒有辦法將任意函數與任意類型捆綁在一起,從容器簽名中刪除它,因此您需要為其使用特征。 幸運的是,特征可以輕松地為任意類型定義和實現,因此您始終可以定義特征並使用特征對象。 特性對象涵蓋了ML / Haskell中通常需要存在性的幾乎所有功能。

而且,在許多情況下,您根本不需要使用特征對象! 例如,上面的print()函數實際上應編寫如下:

fn print<T: ToString>(value: &T) -> String {
    value.to_string()
}

該函數功能更強大,因為它可與ToString trait的任意實現程序一起使用,該實現程序包括由ToString trait對象,以及實現ToString所有其他功能。 通常,唯一使用特征對象的地方是定義異構數據結構時:

let many_to_strings: Vec<Box<ToString>> = vec![Box::new(1), Box::new("foo")];

但是,就像我上面說的那樣,當您使用特征對象時,在大多數情況下,您無需指定需要特征對象-常規的泛型函數會更慣用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM