"overflow while adding drop-check rules" while implementing a fingertree - data-structures

I'm trying to define a finger tree structure and implement its basic operations as an exercise in Rust. I've come up with the following, which is basically what's described in this paper.
use self::FingerTree::{Empty, Single, Deep};
use self::Digit::{One, Two, Three, Four};
enum Digit<A> {
One(A),
Two(A, A),
Three(A, A, A),
Four(A, A, A, A),
}
enum Node<V, A> {
Node2(V, A, A),
Node3(V, A, A, A),
}
enum FingerTree<V, A> {
Empty,
Single(A),
Deep {
size: V,
prefix: Digit<A>,
tree: Box<FingerTree<V, Node<V, A>>>,
suffix: Digit<A>,
},
}
fn main() {
let e: FingerTree<i32, String> = Empty;
}
Compilation gives me an error that I don't understand:
error[E0320]: overflow while adding drop-check rules for FingerTree<i32, std::string::String>
--> fingertree.rs:28:9
|
28 | let e: FingerTree<i32, String> = Empty;
| ^
|
note: overflowed on enum Node variant Node2 field 0 type: i32
--> fingertree.rs:28:9
|
28 | let e: FingerTree<i32, String> = Empty;
| ^
error[E0320]: overflow while adding drop-check rules for FingerTree<i32, std::string::String>
--> fingertree.rs:28:38
|
28 | let e: FingerTree<i32, String> = Empty;
| ^^^^^
|
note: overflowed on enum Node variant Node2 field 0 type: i32
--> fingertree.rs:28:38
|
28 | let e: FingerTree<i32, String> = Empty;
| ^^^^^
Why is this not working? How do I make it work?

You have created an infinite type.
Instantiating FingerTree<V, A> instantiates FingerTree<V, Node<V, A>> which instantiates FingerTree<V, Node<V, Node<V, A>>> which instantiates, ... and there's no end in sight.
The compiler cannot tell that the type will not actually be used at run-time, so prepares itself for the worst. And the worst is infinite.
Simply replacing the type of tree by Box<FingerTree<V, A>> solves the issue, though it may not be correct for the situation at hand.

Related

Calculate sum of chars in parallel [duplicate]

This question already has answers here:
How can I pass a reference to a stack variable to a thread?
(1 answer)
How can I sum up using concurrency from 1 to 1000000 with Rust?
(1 answer)
Closed 3 years ago.
I have an array of strings. I would like to count the total chars but using threads for parallelisation (the original problem is not this but is similar).
use std::thread;
pub fn frequency<'a>(input: &'a [&'a str], worker_count: usize) -> usize {
let handlers: Vec<thread::JoinHandle<usize>> = input
.chunks(worker_count)
.map(|chunk| thread::spawn(calculate(chunk)))
.collect();
let hashes = handlers.into_iter().map(|handler| handler.join().unwrap());
let mut sum = 0;
for h in hashes {
sum += h
}
sum
}
fn calculate<'a>(input: &'a [&'a str]) -> impl Fn() -> usize + 'a {
move || input.iter().map(|s| s.len()).sum()
}
The compiler tells me this:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:5:10
|
5 | .chunks(worker_count)
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 3:18...
--> src/lib.rs:3:18
|
3 | pub fn frequency<'a>(input: &'a [&'a str], worker_count: usize) -> usize {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:4:52
|
4 | let handlers: Vec<thread::JoinHandle<usize>> = input
| ^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `impl std::ops::Fn<()>` will meet its required lifetime bounds
--> src/lib.rs:6:22
|
6 | .map(|chunk| thread::spawn(calculate(chunk)))
| ^^^^^^^^^^^^^
I've tried to remove all lifetimes, use different lifetimes for str and the slice, and explicitly invoke calculate::<'a> but none of those solutions compile.
The input lifetime is the same everywhere: frequency declares 'a that is used in calculate, so the closure is bound to 'a because the captured variables live for 'a.
Where am I wrong?
NB: I would like not to use 'static.

Parsing a string to an enum in F#

I am trying to do the following (which doesn't compile):
let Parse<'T> value =
Enum.Parse(typedefof<'T>, value) :?> 'T
In short I would like to pass an enum type, and a string and get back an enum value.
An example usage would be:
type MyEnums =
| Green = 0,
| Blue = 1
and then:
let r = Parse<MyEnums> "Green"
what would be the syntax? I haven't used generics yet in F#, so this is what I came up with from reading the docs.
bonus question would be if there is a way to parse enums in a case insensitive way (besides turning everything to lowercase for example)
This does compile for me (also without true, did you open System?):
let Parse<'T> value =
System.Enum.Parse(typedefof<'T>, value, true) :?> 'T
and works case-insensitive for
type MyEnums =
| Green = 0
| Blue = 1
Parse<MyEnums> "Green" // Green
Parse<MyEnums> "blue" // Blue
I came up with this in a hurry, which I believe has the advantage of not accepting other types than enums. Haven't had time to google for a better way, if there is one. Also, the underlying type must be int, and I haven't had time to see if there's something to be done with that either.
type MyEnum = | A = 1 | B = 2
let parseEnum<'T when 'T : (new : unit -> 'T) and 'T : struct and 'T :> ValueType and 'T : enum<int>> v =
match Enum.TryParse<'T> v with
| true, v -> Some v
| false, _ -> None
let x = parseEnum<MyEnum> "B"
match x with
| Some x -> printfn "%A" x
| None -> printfn "Sorry"
// let z = parseEnum<int> "1" // won't compile

Using the Bellman-Ford algorithm from petgraph

I would like to use the Bellman-Ford algorithm from the petgraph crate. Here is a very simple sample program which does not compile:
extern crate petgraph;
use petgraph::prelude::*;
use petgraph::dot::{Dot, Config};
use petgraph::algo::bellman_ford;
fn main() {
println!("Hello, world!");
let mut deps = Graph::<&str, u64>::new();
let a = deps.add_node("later");
let b = deps.add_node("hello");
deps.update_edge(a, b, 5);
deps.update_edge(b, a, 10);
let result = bellman_ford(deps, NodeIndex::new(0));
}
When I compile this program I get this error message:
error[E0277]: the trait bound `petgraph::Graph<&str, f64>: petgraph::visit::IntoNodeIdentifiers` is not satisfied
--> src/main.rs:16:18
|
16 | let result = bellman_ford(deps, NodeIndex::new(0));
| ^^^^^^^^^^^^ the trait `petgraph::visit::IntoNodeIdentifiers` is not implemented for `petgraph::Graph<&str, f64>`
|
= help: the following implementations were found:
<&'a petgraph::Graph<N, E, Ty, Ix> as petgraph::visit::IntoNodeIdentifiers>
= note: required by `petgraph::algo::bellman_ford`
error[E0277]: the trait bound `petgraph::Graph<&str, f64>: petgraph::visit::IntoEdges` is not satisfied
--> src/main.rs:16:18
|
16 | let result = bellman_ford(deps, NodeIndex::new(0));
| ^^^^^^^^^^^^ the trait `petgraph::visit::IntoEdges` is not implemented for `petgraph::Graph<&str, f64>`
|
= help: the following implementations were found:
<&'a petgraph::Graph<N, E, Ty, Ix> as petgraph::visit::IntoEdges>
= note: required by `petgraph::algo::bellman_ford`
From what I have gathered, the implemented Bellman-Ford algorithm works with floats, not integers.
Using floats instead of the u64 and referencing deps later does the trick:
use petgraph::algo::bellman_ford;
fn main() {
let mut deps = Graph::<&str, f64>::new();
let a = deps.add_node("later");
let b = deps.add_node("hello");
deps.update_edge(a, b, 5.0);
deps.update_edge(b, a, 10.0);
let result = bellman_ford(&deps, NodeIndex::new(0));
println!("{:?}", result);
}

Breadth first search and lifetimes

I want to write a function that uses breadth-first search on a binary tree to print node values in order:
use std::collections::VecDeque;
use std::ops::Deref;
struct BinarySearchNode<'a> {
value: &'a str,
key: i32,
left: Option<Box<BinarySearchNode<'a>>>,
right: Option<Box<BinarySearchNode<'a>>>,
}
impl<'a> BinarySearchNode<'a> {
pub fn print(&self) -> String {
let mut queue = VecDeque::new();
let mut output = String::new();
queue.push_back(&self);
while let Some(ref current) = queue.pop_front() {
if let Some(left_node) = current.left {
queue.push_back(&left_node.deref());
}
if let Some(right_node) = current.right {
queue.push_back(&right_node.deref());
}
output = output + current.value + "\n";
}
output
}
}
fn main() {}
I get the error
error: borrowed value does not live long enough
--> src/main.rs:19:34
|
19 | queue.push_back(&left_node.deref());
| ^^^^^^^^^^^^^^^^^ does not live long enough
|
note: reference must be valid for the block suffix following statement 0 at 13:40...
--> src/main.rs:13:41
|
13 | let mut queue = VecDeque::new();
| ^
note: ...but borrowed value is only valid for the statement at 19:16
--> src/main.rs:19:17
|
19 | queue.push_back(&left_node.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
--> src/main.rs:19:17
|
19 | queue.push_back(&left_node.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `left_node` does not live long enough
--> src/main.rs:19:34
|
19 | queue.push_back(&left_node.deref());
| ^^^^^^^^^
|
note: reference must be valid for the block suffix following statement 0 at 13:40...
--> src/main.rs:13:41
|
13 | let mut queue = VecDeque::new();
| ^
note: ...but borrowed value is only valid for the if let at 18:12
--> src/main.rs:18:13
|
18 | if let Some(left_node) = current.left {
| ^
error: borrowed value does not live long enough
--> src/main.rs:22:34
|
22 | queue.push_back(&right_node.deref());
| ^^^^^^^^^^^^^^^^^^ does not live long enough
|
note: reference must be valid for the block suffix following statement 0 at 13:40...
--> src/main.rs:13:41
|
13 | let mut queue = VecDeque::new();
| ^
note: ...but borrowed value is only valid for the statement at 22:16
--> src/main.rs:22:17
|
22 | queue.push_back(&right_node.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
--> src/main.rs:22:17
|
22 | queue.push_back(&right_node.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `right_node` does not live long enough
--> src/main.rs:22:34
|
22 | queue.push_back(&right_node.deref());
| ^^^^^^^^^^
|
note: reference must be valid for the block suffix following statement 0 at 13:40...
--> src/main.rs:13:41
|
13 | let mut queue = VecDeque::new();
| ^
note: ...but borrowed value is only valid for the if let at 21:12
--> src/main.rs:21:13
|
21 | if let Some(right_node) = current.right {
| ^
error[E0507]: cannot move out of borrowed content
--> src/main.rs:18:38
|
18 | if let Some(left_node) = current.left {
| --------- ^^^^^^^ cannot move out of borrowed content
| |
| hint: to prevent move, use `ref left_node` or `ref mut left_node`
error[E0507]: cannot move out of borrowed content
--> src/main.rs:21:39
|
21 | if let Some(right_node) = current.right {
| ---------- ^^^^^^^ cannot move out of borrowed content
| |
| hint: to prevent move, use `ref right_node` or `ref mut right_node`
I needed to deref() because simply using the operator * was causing a type mismatch as it expected a reference and not a box. It seems those dereference slightly differently and at least in stable I can't destructure it either.
I get that this value is scoped within the while loop and doesn't live long enough to be in the VecDeque (if this is the right data structure for the job) but I'm not sure what the best way to go about extending that lifetime is or if there's simply a better way to write this entire thing as it feels a bit complex.
My main problem is that I'm not sure where to start refactoring this code and I surprisingly had a hard time finding examples of a breadth-first search performed on a binary tree in Rust to take patterns from.
Your main problem lies in this line (and the right version):
if let Some(left_node) = current.left
This tries to move the value contained in current.left into the pattern on the right side. the problem is that current.left is an Option<Box<BinarySearchNode<'a>>>. When you move the Box out of current, that would leave current without a valid value for left! Accessing that value in the future would lead to bad behavior.
Instead, you need to leave the value where it is and instead take a reference. The two main ways are to use the ref pattern modifier:
if let Some(ref left_node) = current.left
Or to call as_ref:
if let Some(left_node) = current.left.as_ref()
Here is complete code:
use std::collections::VecDeque;
struct BinarySearchNode<'a> {
value: &'a str,
key: i32,
left: Option<Box<BinarySearchNode<'a>>>,
right: Option<Box<BinarySearchNode<'a>>>,
}
impl<'a> BinarySearchNode<'a> {
pub fn print(&self) -> String {
let mut queue = VecDeque::new();
let mut output = String::new();
queue.push_back(self);
while let Some(current) = queue.pop_front() {
if let Some(left_node) = current.left.as_ref() {
queue.push_back(left_node);
}
if let Some(right_node) = current.right.as_ref() {
queue.push_back(right_node);
}
output = output + current.value + "\n";
}
output
}
}
fn main() {
let root = BinarySearchNode {
value: "a",
key: 0,
left: Some(Box::new(BinarySearchNode {
value: "b",
key: 1,
left: None,
right: None,
})),
right: Some(Box::new(BinarySearchNode {
value: "c",
key: 2,
left: None,
right: None,
})),
};
println!("{}", root.print());
}
Try this one:
pub fn print(&self) -> String {
let mut queue = VecDeque::new();
let mut output = String::new();
if let Some(ref left_node) = self.left {
queue.push_back(left_node);
}
if let Some(ref right_node) = self.right {
queue.push_back(right_node);
}
while let Some(ref current) = queue.pop_front() {
if let Some(ref left_node) = current.left {
queue.push_back(left_node);
}
if let Some(ref right_node) = current.right {
queue.push_back(right_node);
}
output = output + current.value + "\n";
}
output
}

How should I modify my Queue class to allow users to create empty queues of unspecified type in F#?

I have created an immutable Queue in F# as follows:
type Queue<'a>(f : 'a list, r : 'a list) =
let check = function
| [], r -> Queue(List.rev r, [])
| f, r -> Queue(f, r)
member this.hd =
match f with
| [] -> failwith "empty"
| hd :: tl -> hd
member this.tl =
match f, r with
| [], _ -> failwith "empty"
| hd::f, r -> check(f, r)
member this.add(x) = check(f, x::r)
static member empty : Queue<'a> = Queue([], [])
I want to create an instance of an empty Queue, however I get a value-restriction exception:
> let test = Queue.empty;;
let test = Queue.empty;;
----^^^^
C:\Documents and Settings\juliet\Local Settings\Temp\stdin(5,5): error FS0030:
Value restriction. The value 'test' has been inferred to have generic type
val test : Queue<'_a>
Either define 'test' as a simple data term, make it a function with explicit
arguments or, if you do not intend for it to be generic, add a type annotation.
Basically, I want the same kind of functionality seen in the Set module which allows me to write:
> let test = Set.empty;;
val test : Set<'a>
How can I modify my Queue class to allow users to create empty queues?
You need to use GeneralizableValueAttribute, a la:
type Queue<'a>(f : 'a list, r : 'a list) = // '
let check = function
| [], r -> Queue(List.rev r, [])
| f, r -> Queue(f, r)
member this.hd =
match f with
| [] -> failwith "empty"
| hd :: tl -> hd
member this.tl =
match f, r with
| [], _ -> failwith "empty"
| hd::f, r -> check(f, r)
member this.add(x) = check(f, x::r)
module Queue =
[<GeneralizableValue>]
let empty<'T> : Queue<'T> = Queue<'T>([], []) // '
let test = Queue.empty
let x = test.add(1) // x is Queue<int>
let y = test.add("two") // y is Queue<string>
You can read a little more about it in the language spec.

Resources