Overview

rovv is a crate to provide a "poor-man's" row-polymorphism for rust base on lens-rs.

What is row poly?

In programming language type theory, row polymorphism is a kind of polymorphism that allows one to write programs that are polymorphic on record field types (also known as rows, hence row polymorphism).

-- wikipedia

Considering a function in PureScript:

purescript \r -> r.x

you can pass a record into the function above

purescript { x: 1 }

or even

purescript { x: 1, y: 2, z: 3 }

That is what "row-poly" means: a record can be passed into the function above as long as it contains a field .x.

The type of the function is:

purescript { x: a | l } -> a -- The label `l` represents the rest fields of a record.

Now you can do the same(not exactly) in rust.

Usage

restrict the parameter r contains a field .x

```rust fn take_x(r: row! { x: T, .. }) -> T { r.view(optics!(x)) }

// &row! { x: T, .. } is ok fn takexref(r: &row! { ref x: T, .. }) -> &T { r.view_ref(optics!(x)) }

// &mut row! { x: T, .. } is ok fn takexmut(r: &mut row! { mut x: T, .. }) -> &mut T { r.view_mut(optics!(x)) }

let foo = Foo { // have been derived Lens for Foo x: String::from("this is Foo"), y: 1234 }

let bar = Bar { // have been derived Lens for Bar x: 0, z: Some(1) }

asserteq!(&*takexref(&foo), "this is Foo"); asserteq!(take_x(bar), 0); ```

You can also describe a type may have a field:

```rust fn ortakey(r: row! { y: T?, .. }) -> Option { r.preview(optics!(y)) }

asserteq!(ortakey(foo), Some(1234)); asserteq!(ortakey(bar), None); ```

Desugar

The function take_x is equivalent to

rust fn take_x<T, R>(r: R) -> T where R: Lens<Optics![x], T> { r.view(optics!(x)) }

In fact the row! { .. } will be desugared to the impl trait, the placeholder of a type satisfied the lens trait. And the dyn_row! { .. } will be desugared to the dyn trait, the dynamic version of row!.

rust fn sum_field(n: i32) -> Box<dyn_row! { Ok: i32?, Err: String?, Some: ()? , ..}> { match n%3 { 0 => Box::new(Result::<_, String>::Ok(0)), 1 => Box::new(Result::<i32, _>::Err(String::from("no!"))), 2 => Box::new(Some(())), _ => Box::new(Option::<()>::None) } }

Limitations

Cargo.toml

Please add the following in your Cargo.toml

```toml [dependencies] lens-rs = "0.3" rovv = "0.2"

[package.metadata.inwelling] lens-rs_generator = true rovv = true ```

Enjoy it!