Quantcast
Channel: Dafny: An Automatic Program Verifier for Functional Correctness
Viewing all articles
Browse latest Browse all 1106

Commented Unassigned: Incorrect 'cyclic dependencies' error for datatypes [129]

$
0
0
The following code works:

```
datatype Maybe<T> = None | Some(v:T)
datatype B = B(b:Maybe<B>)
```

However, the variation below causes the error "because of cyclic dependencies among constructor argument types, no instances of datatype 'B' can be constructed":

```
datatype Maybe<T> = Some(v:T) | None
datatype B = B(b:Maybe<B>)
```

Comments: To satisfy itself that a datatype has some instance, Dafny looks for a constructor for which it already knows how to instantiate all its arguments. Dafny records the constructor it finds that achieves this, and it also keeps track of which of the datatype's type parameters played a role in the instantiation. For example, this gives Dafny a way to allow the following type declarations: ``` datatype List<T> = Nil | Cons(T, List<T>) datatype Tree<T> = Nodes(children: List<Tree<T>>) ``` Here, the `Nil` constructor gives a way to create an instance of `List<T>` without needing an instance of type `T`. Therefore, the `Nodes` constructor gives a way to create an instance of `Tree<T>`, because it is possible to create a `List<Tree<T>>` without already needing an instance of type `Tree<T>`. There can be choices in which constructor to pick. For example, consider: ``` datatype Snake<X,Y> = Front(X) | Back(Y) | Next(Snake<X,Y>) datatype FChain<T> = Link(Snake<T, FChain<T>>) datatype BChain<T> = Link(Snake<BChain<T>, T>) ``` Here, an `FChain<T>` can be created by using the `Front` constructor to create a `Snake<T, FChain<T>>`. Similarly, a `BChain<T>` can be created by using the `Back` constructor to create a `Snake<BChain<T>, T>`. However, Dafny tries the constructors of a datatype in order and it stops as soon as it finds one whose arguments it knows how to construct. This seems like a pretty good strategy, since keeping track of all possibilities would give an exponential algorithm. Plus, the situation where more than one constructor is needed is probably rare. The strategy is problematic for the `Maybe` example above. The following tweak of the existing algorithm would solve the problem: Don't stop as soon as one instantiable constructor is found. Instead, figure out all instantiable constructors and then pick the best among these. As a simple and reasonably efficient way to pick the "best", I suggest picking an instantiable constructor that requires a minimal number of already constructed type arguments, and to break ties among these, pick the first one listed. This would pick `None` over `Some`, regardless of the order in which these are listed. It would also still allow the `Tree` example above. It would continue to disallow `BChain` -- oh, well. Rustan

Viewing all articles
Browse latest Browse all 1106

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>