在Rust中是否有支持“map”功能(如Haskell)的集合?

时间:2017-04-29 06:24:37

标签: rust

在函数式编程语言中,集合上最原始/最基本的操作是同态map;它(大致)Collection[A] -> (A->B) -> Collection[B]

Rust系列似乎不支持这一点。我想这是因为它们是可变的集合;如果您已经在使用可变集合,则就地更新会更有效。

我错过了一个单独的“不可变集合”库(比如Scala)吗?

使用A->BCollection[A]变为Collection[B]的“就地映射”操作怎么样(与ML和Haskell不同,它实际上可以安全地做到这一点因为仿射类型!)甚至是A=B和就地地图采用A->A的特殊情况?

很难用搜索引擎回答这个问题,因为所有的点击都涉及“映射”名词(如HashMap)。

2 个答案:

答案 0 :(得分:3)

要将容器映射到容器,请迭代并collect()

vec.iter().map(|x| x * 2).collect::<Vec<_>>();

要在原地更改项目,请使用for循环和iter_mut()。不建议在这种情况下使用迭代器链接,因为修改值会引入副作用。

for x in vec.iter_mut() { 
    x *= 2; 
}

答案 1 :(得分:3)

Rust有一个map()函数,但它不是每个容器的一部分,而是特征Iterator(Rust特征非常类似于Haskell的类型类):Iterator:map()。该特征包含许多更有用的方法,其中许多对于FP程序员来说应该是熟悉的。

让我们看看map()的实际效果:

let result: Vec<_> = vec![2, 3, 5, 7]
    .into_iter()      // we have to get an iterator over the vector 
    .map(|i| i * i)   // next we map each element
    .collect();       // finally we collect all elements into a new vector

map()的类型是您所期望的:

:: Iterator a -> (a -> b) -> Iterator b

或者在Rust语法中:

trait Iterator {
    type Item;
    fn map<B, F>(self, f: F) -> Map<Self, F> 
        where F: FnMut(Self::Item) -> B;
}

首先看起来更复杂,但它确实有意义,将来可能会更好。签名是(self, f: F) -> Map<Self, F>。和

  • self Iterator超过Self::Item [比较:Iterator a]
  • FFnMut(Self::Item) -> B [比较:(a -> b)]
  • Map<Self, F>对于Iterator返回F [比较B]
  • 而言Iterator ba -> a

如果你想做一个就地let mut v = vec![2, 3, 5, 7]; for e in &mut v { e *= 2; } let mut m = HashMap::new(); m.insert("anna", 5); m.insert("peter", 3); for v in m.values_mut() { v *= 2; } 地图(意思是:没有变换类型),你可以获得对每个元素的可变引用并进行更改。例如:

inputs n=4

如果没有不安全的代码,目前无法执行更改类型的就地映射。部分原因是Rust的类型系统无法在编译时比较两种类型的大小(但它会改变)。