rovv
is a crate to provide a "poor-man's" row-polymorphism for rust base on lens-rs
.
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.
restrict the parameter r
contains a field .x
```rust
fn take_x
// &row! { x: T, .. } is ok
fn takexref
// &mut row! { x: T, .. } is ok
fn takexmut
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
asserteq!(ortakey(foo), Some(1234)); asserteq!(ortakey(bar), None); ```
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)
}
}
row!
is used in argument position now,
because the row!
is the impl trait.dyn_row!
will lose some polymorphism e.g. dyn_row! { x: i32, .. }
does not satisfy dyn_row! { ref x: i32, .. }
,
because the trait object cannot convert to the others, thought Trait1: Trait2.dyn_row!
.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!