>> Bruce: Good afternoon, everyone. I'm Bruce Delano [phonetic], and I'm very pleased to introduce Nada Amin who has been spending, well, a week with us and will spend this week as well. But before then she has done a lot of work with using Dafny and she's now learning how to hack in the Dafny sources as well to add the improvements that she would like. Now, Nada has like a developer history as well from having worked at Microsoft as an intern some number of years ago. And worked at Google as a developer as well, right, in Zurich and is now at EPFL studying for her Ph.D. with Martin Odersky. So take it away. >> Nada Amin: Thank you. Thank you for inviting me to MSR. It's been a lot of fun to dabble with Dafny internal. It's going to be from a user perspective. I've been using Dafny to do meta theory of programming languages and I've done both textbook examples and research level paper examples and also used it in my own research where I wasn't really sure where I was going and using Dafny to guide me a little bit both in the design and in the proofs. But for this talk I'll start with the textbook example, which is modeling the simply typed lamda calculus and mechanically proving the semantic types on this and what I hope to convey here is that in terms of modeling Dafny doesn't really bring so much more than [indiscernible] talk but it's when you do the proofs that you get a lot of mileage out of using Dafny. So first we'll still look at the model, and I'm starting to define some -- here I'm defining a data type for option which is really just kind of like the maybe [indiscernible] or something like this, and I'm using it because I often want to use, have functions that sometimes return a result and sometimes not. Like the step function of operational semantics or the typing function. Not every term has a type. So I'll be using the option one for this. And then for my base types for the simply typed lambda calculus, I'll have this opaque base type to start with. So this is just some type that you can't really match anything else against except itself. And then recursively you define this arrow type which takes a parameter type and a return type. T 2. And then for the terms, we have variables, application and abstraction. And actually here I should just say the abstraction also takes the type T. Okay. So in terms of -- yeah? Is there any question. >>: No, no. >>: I have a question. Is the variable going to be represented by just concrete names or ->> Nada Amin: Yeah, I'm using integers as concrete names. I'm not using any fancy encoding. For the purpose of this calculus this is going to be enough because we're only dealing with close terms so we don't have any issues with variable capture. But of course if we want to extend this to other settings like, for example, in system F where you also have type applications and here you can have capture, it will need to -- we'll need to be a bit more sophisticated. But here I'm using the simple encoding and this is also the same as the encoding used in the COC [phonetic] development from foundations of software. Okay. So in terms of operational semantics, we just define what is a value in our language, and for here we'll say that any lambda, any lambda abstraction is a value. And then here there's some boilerplate in terms of defining free variables and substitution. So the interesting case is really that so F of V says that it computes the set of fee variables of term T and interesting case is if we have a variable then we just return its ID in the set. If we have an abstraction, then we compute the fee variables of the body but we remove the bound variable X because it's not free. It's bound. And then the other case are just recursing over and unioning the free variables we find. >>: So with that, the union have to define all the set what they are and what they are not. And what you get here -- >> Nada Amin: So Dafny has a primitive for a set and it knows already about -- it has already some axioms about sets. So it knows things such that if you remove X from the set here, then this whole, this set here will not have X anymore in terms of variables. Does this answer your question? >>: Okay. >> Nada Amin: Any more questions? And then substitution is also a bit boilerplaty but it's the same pattern. So if we have a variable X prime, so just to recap substitution says that we have a term T. And we replace all three occurrences of X with S, another term S. And interesting case is if we have a free variable X prime then we just go ahead and do the substitution if it matches, if the variable matches. Otherwise we leave the term unchanged. And here this is where Nikil's [phonetic] comes in because we're only dealing with -- we're only dealing with cases where S is closed. So this is okay. In general, if S can have free variables, let's say S had this variable X prime, then we're doing the substitution -- we have S here, and this X prime would capture the free variable X prime that is in S. So we're assuming that S is closed and this will show up in the proofs as well. But for now we're not worrying about it so much. And then application is just a recursive case. So with this we can define -- yes? >>: Is it easily fixed? Right? >> Nada Amin: Uh-huh. >>: You don't need more fancy encoding, kind of just remove, what you have to do, remove the X -- >> Nada Amin: So what I could do is this is a bound variable. This is a bound variable. So I could rename it to something else. But then if you start to do renaming, you could do that, but then you also need a way to compare terms that have different names but are still equivalent. >>: That's really difficult. >> Nada Amin: That's a FI equivalence. But it's doable. I think using a different encoding might be useful. In COC they have this library for locally nameless encoding where you use [inaudible] indices for when you're in a local setting, with bound variables, but in a global setting you still use these names. So we could do things like this. I've played with this. But, yeah, for this example I'm glossing over that. >>: You could still use concrete names and just alpha convert T before substituting, but you don't necessarily need to reason about alpha equivalence distribution type tactic. >> Nada Amin: Maybe not in this case but I was thinking ahead of cases where you would need to. >>: You can do renaming -- >> Nada Amin: No, it's fine. I don't mind interruptions, but I'll show later how you can do this as well like this. So for the reduction relation. So here we see that if we compare with any other language we have less specificities for pattern matching because we can't really have nested pattern matching like here I have to explicitly have these statements but this is basically saying if I have an application and the function part is an abstraction and the argument part is a value then I can go ahead and do a better reduction. So the substitution. Otherwise, these are just congruent cases. Again, I can step on the function side or I can step on the argument side. And I chose to make my function deterministic. Anyway, it's going to be deterministic because I'm using these if statements but I'm just being explicit about the fact that I'm only stepping on the argument when F is already a value. Okay. And then you can define a multi-step relation. And this is really if you look at the step function and think of it as -- it's a partial function. So think of it as a relation and then this is really just a reflexive transitive closure of that relation. And here we're taking N for the number of steps we're doing. Okay. So we can do some examples and this one Dafny figures out automatically. And now on to typing. >>: [indiscernible]. >> Nada Amin: Yeah. So this is just saying if I write it in and I have lambda X which takes a base type and returns X and then I'm applying this to lambda X then that just returns lambda XVX. >>: The first name is BLB [phonetic]. >> Nada Amin: >>: Is this the recent extract? >> Nada Amin: >>: No, not yet. This one was proved automatically. This is just one step. >> Nada Amin: zero. >>: Yeah, you're right. This is just one step. N just has to be greater than But for something more of a [indiscernible] function application? >> Nada Amin: Yeah, uh-huh. This was just to -- it's like writing a test with -- yeah. All right. So typing. So first I'm using maps. This is also a Dafny data type. Internal data type to represent a partial map from variable names to types. And you can look things up in the map. So I'm just -- and you can extend the map as well. So I'm going to use these abstractions over it. And the typing relation is syntax-directed. So we have one case for absent an app and here we see that, okay, it's not that pretty because of this [indiscernible] but that's why I've put these checks a bit here so that they don't affect the main flow, which is here. So for a variable we just look it up in the context. For an abstraction, we type the body in extended context, and then return an arrow type where the type of the body is in the result of the arrow. And then for application we just type the function and the argument and we check that the function is actually an arrow and it agrees with the argument, and then we return the result of the function. Okay. So now we're done with our model. >>: Can I ask a question, you chose to write the typing relation as a function in the simply typed lambda calculus is easily natural. But one would normally write it as a relational -- >> Nada Amin: Yeah, I can also do this. In my own research work I've mostly used relations. And it makes more sense because even there sometimes I wasn't sure if something is decidable then you don't have a choice which is a relation. And you can also work with the undecidable things if you also have a step index and things like this. And what's nice in Dafny is that mutual induction works really nicely. Even if you have a step index, you can -- it makes it really easy to do mutual induction on things. >>: You have a bar here -- >> Nada Amin: >>: Of the body. >> Nada Amin: >>: It's just a variable. Oh the vary -- yeah. Let's see. Oh, wow. >> Nada Amin: >>: Varies. You have the write decrease as T [phonetic]. >> Nada Amin: >>: CR 2 [phonetic]. [indiscernible]. >> Nada Amin: >>: Semantic of what, sorry? Yes, I guess it's getting. Not very smart about it. >> Nada Amin: It's getting confused because here we're extending the context. So the context is not decreasing. >>: But the second is always decreasing. >> Nada Amin: But it has some default so here -- >>: Complaint services [phonetic]. >>: What if you had -- [cross talk] . >> Nada Amin: If I switched the parameter it would have worked. Because it works ->>: By default it's -- graphic of the argument in the order given. >>: Sorry I was still falling off my chair. >> Nada Amin: So here are some examples, again. This is just testing. Not proofs yet. And here we actually have to do more work in some cases. And the reason is that Dafny just does a bit of unfolding and not much. I'm finally understanding this, but we have some ideas on how to change this so that you wouldn't need to assert the intermediate steps. But anyway that was just to give some examples. We don't need to go to them in detail. I want to get to the type ST properties. going to ->>: Why is it you're working using integers instead of variables. >> Nada Amin: >>: Because Dafny doesn't have strings. Yeah. The integer -- >> Nada Amin: >>: Like names, you mean? Yes. >> Nada Amin: >>: For type ST [phonetic] we're Yeah. Integer terms of -- >> Nada Amin: Okay. So for the type ST theorems we're going to do syntax on this. So progress and preservation. And the way to read this ghost method is really just something that's there for verification so it doesn't get compiled into code. And the way to read it is that it requires clauses are like hypothesis of your demo or theorem. And insure clause are like conclusions. So here we're saying if term T has a type and the empty context, then either it's a value or it's steps. It can take some steps. First let's just look at how this is done on paper and COC to prove this. Is this readable? So on paper you really would do a induction on the typing variation. There are a few cases it's pretty straightforward, but you have to still reason through them. In COC, this is how it would look. It's a fairly long proof. And already it's using some automation with these dot, dot, dot. And, yeah, so that's the end of the proof. >>: So magic things. You have to destruct or -- >> Nada Amin: Yes, so you need to understand this tactic language. So, for example, this is saying ->>: Destruct. >> Nada Amin: Yeah. Yeah, this is doing induction on the derivation, and then when here we're going to use -- it's hard to read without having the context, the interactive context of the proof. But anyway I wanted to give you a flavor what it looks. >>: The interesting thing is you have to know a lot about the [indiscernible] engine to guide it in the right way. That's what I call the magic words like [indiscernible] or diversion or something, guide it along. >> Nada Amin: [laughter] [applause] And this is how it looks in Dafny. Nothing. >> Nada Amin: So not all proofs are going to be that easy. But this one it figured out automatically. Because, yeah, it's just an induction on the typing derivation, so it could fill this out. >>: Induction on the piping derivation or on the term? >> Nada Amin: I think here it's doing it on the term. But what happens is it has this hypo thesis, which is the type. So at the end it can really, when it's in the -- say when it's the abstraction case, it can use the induction hypo thesis from, that comes from this typing the full abstraction. So at the end it's equivalent to doing a typing derivation on the term, because you're kind of doing a case analysis. I'll show another example of this data. >>: [indiscernible] comparison because when you show it [indiscernible] you say it's a text [indiscernible] [indiscernible] everything and nothing is automatic -- >> Nada Amin: That's fair but it's kind of the default way to do things. If you want to go fancy in COC, it actually takes some thinking to really automate and do proofs that are modular. But in Dafny it kind of comes for free. Okay. So now we're going to do preservation using the substitution lemma first. And here are just some lemmas that I also took from the textbook. And Dafny proved them automatically. So here I had to give a hint to Dafny that says do an induction where you generalize over both C and T. And the reason -- whoops. The reason you need to generalize over the context as well is because you have the abstraction case. So anyway this says that if X is a free variable of T, and T has some type and some context, then this context definitely has -definitely binds X. >>: So I was wondering about the process by which you arrived at these ways of stating things. So you wrote the progress thing where you weren't surprised -- >> Nada Amin: I was surprised. >>: When you got to the lemma free context how did you discover that maybe you tried the first time to see if it would go through automatically and it probably didn't. >> Nada Amin: Okay. So let's remove this. So here it's going to complain that something -- and this one is actually a bit of a tricky one. There's a bit of a bug. So I'm just going to -- I mean, I'm just going to go through it but just gloss over this bug. So here it says it doesn't know how to proof -- oh. Not yet. >>: Still working. >> Nada Amin: Yeah. Wait. That worked. Oh, that's weird. Okay. So this one is a bit buggy. But, yeah, this doesn't make much sense if you repeat -- but in general I'll show how ->>: Showed the error message? >> Nada Amin: >>: Yeah, so it just doesn't know. Oh, right. >>: So if you add insures, maybe Dafny gets help just a little bit more in how to find -- >> Nada Amin: Yeah, I think so. There's something strange going on with this example. But usually it's a bit more straightforward. So I'll show some examples later of how you do some derivations. Okay. So then we're only interested in close terms. So this is how we define closed terms. Just saying that X -- for any variable X it's not in the free variables of T. >>: Why don't you just say F of VT -- >> Nada Amin: It could have been simpler. Yeah. But anyway I wanted to do a proof by contradiction. So here you go. So while I guess I could have done it in the other way. But so here I'm seeing a corollary of the previous thing is that if you are typeable in MT context then you're closed. And I'm doing this by I have to reproduce this pattern here. So I have this for all parallel statement kind of that says, well, for all X we're going to ensure that X is not in the free variable of T. And I'm doing this by first assuming that it is. And then showing that you get a contradiction because if it's in the free variable of T, then by the previous lemma we know that it must be in this context but this context is empty. So I think maybe if I tried to change it as you said, this proof would also look simpler. Okay. So one more it's just a context invariance. I'm not -- again it's one that's proved automatically. It's just saying that if C and C prime agree on all free variables of T, then they should agree on the type as well. Okay. So now this is we're coming to the hardest part which is the substitution lemma. And this is also notoriously tricky in many calculus once you do extensions. So this says that basically substitution preserves typing. And this statement is actually a bit hard to read. The reason is that I don't want to be adding extra variables here. So I can't really -- the only way I have of referring to this type, which I know it has some type and the only way I have of referring to it is by this expression. Like this dot get. But this basically says that if S has some type S capital S in an empty context and T has type T in a context extended with X having type S, then if you do the substitution you have the same type as well. And really the only interesting case when we did the model was for variable and application. So this is the only cases where we have to guide Dafny a little bit. And we're using the previous lemmas in key places. Okay. >>: So you mean you have to guide Dafny by writing the insert or by -- >>: Exactly. >>: Or the responsive terms. >> Nada Amin: So the way this works, let's say I comment this out. Well, okay, yeah, so then it's complaining and the squiggly is here, which means that it's really like a different case that is complaining about. So then I can try to figure this out by doing like say TF, for example, this is the problematic case. And then I do FTVAR. Is this the problematic case? And then just add this. So then it's complaining -- well, it was complaining about this case. So I know that this is the case that I need to worry about. >>: [indiscernible]. >> Nada Amin: So then it tells me I need to show this post condition holds for this case. Yeah. So it's saying this post condition here with this squiggly doesn't -- it doesn't know that it's hold for this case. So I need to help it. And the way I help it is by saying, well, okay if you look at the TVAR case, if you look at actually the way it was done in the has type function -- let me make this -- if you look here, then you see that well actually in the substitution, what you see is that it has these two cases so if X is equal to X prime then SST. So that means that here I really have two cases to consider. If the ID is equal to X as this, and now we see that Dafny is really confused only about this case. And so now I can keep drilling and understand why is this case tricky. Well, the reason it's tricky is that we're actually using the -- so this is the case where we're doing the substitution. And the reason it's tricky is that we're actually using the fact that S is closed to do the context invariance. >>: So like if you don't know the proof apriori, let's say you can dig, but it's nothing you can gain -- >> Nada Amin: In some ways it's like -- so COC gives you the interactive context and says this is the case you need to worry about. Here is the same but you have the flexibility in choosing which order you do the case because you know what you're doing a derivation on ->>: I know, but when I look at this proof and what you say there's nothing that tells me that's what I have to do. >> Nada Amin: Yeah, so it's interactive. You try it out. >>: But I really don't understand why you assert the equal equal is. >> Nada Amin: Why it's there? Maybe it doesn't -- it's also just for my understanding. I know that I'm in the case that is a variable, and where the substitution is happening. So I know that I'm substituting -- X is just -- T is just X and I'm doing the substitution. So this whole thing just becomes S. So then the type of this thing, which was T, we defined it to be T. We know this has to be the same as S. >>: You have like [indiscernible] or something that can give intermediate status of why it's confused or something like that. >> Nada Amin: There's a way but I haven't used debugging support much. Okay. So now for preservation, it's really just using the substitution lemma where it applies and the rest it applies automatically. That's it. We're pretty much done. I'm defining what is a normal form. And stuck is a normal form that isn't a value. And then I can show type standards by using this progress and preservation. So that's the generic part. So now what I want to show is how modular the proofs are. What I did is I added some extensions. So I added boolean types. Natural types. I also added isorecursive types, which are the fold/unfold operation. I'll show you an example of this later. And this is like -- Dafny doesn't have pragmas, I basically can comment this in and out and what's interesting is that the model has to change. Right? The model is changing I mean my values now include natural numbers and these faults. And then so the model changes quite a bit. And that's expected. I mean, after all, you're doing a new calculus. But then what's really interesting is that for this case -- sorry. I'm just going to scroll down. And just to show I'm actually using this, so I have examples of boolean naturals and this fold thing. But what's interesting is that the type [indiscernible] properties stay the same. So the proofs that we had before are exactly the same. Nothing has changed. And the reason is that if you look at the proofs, the only interesting parts are for abstraction and variables and the application parts really wasn't mentioned anywhere and so this new stuff is still by induction on the congruent and everything just works. And I added this isorecursive type because I actually wanted to find a case where it doesn't work and so that I could show how I would extend the proof but it still works. So I got -- yeah. So I think that's pretty cool. I mean, if you look at how to achieve this in COC you really need to have the insight beforehand to structure your proofs in the right way. And just to show that things are actually working nicely. So if I add the mistake, for example, if an S type, I change -- I change the if statement so that -- if expression so it doesn't check that both branches are the same. Then hopefully I should get some error somewhere. So this tells you when it's done. I haven't enabled the caching because it wasn't -there was some issues with it. But this should tell you when ->>: Too fast and blow up the audience. >> Nada Amin: Yes, so it says that it can't proof preservation anymore. So you can begin on what the problem is I can say F is the problem and T if. Well, here I know it's there. But I'm just going to have a suspicion or I could even ask it is the problem with T full, for example? Or is it the problem somewhere else? And it tells me, yeah, the problem is here. And since here I'm doing -- I'm kind of doing a case analysis on the stepping functions. Yes, so here it's recomputing, because when there's the purple line it's recomputing. So I know that the problem is here, and I can look at the stepping function. And I have the three cases here. So it says it cannot show this. And if I add these three cases to tell me which one is it's complaining about. >>: If you get -- >> Nada Amin: >>: Yeah. So you need IDE support for this -- >> Nada Amin: Yes, otherwise it's hard. You can also -- it would be too much -- the cycle would be too slow if you do it from the command line. >>: No, no, I meant proof debugger. You But it seems like -to sort of have some simulate the event. that each edit should be supported by some sort of shouldn't be having to modify that sort of thing. well, okay. It seems like there's an opportunity notion of a proof debugger that's allowing you to >>: Sort of like the -- a strategy where you can say basically it shows you all the different places you have to consider, you could do it here or in line the different data that you need to consider. >> Nada Amin: That's true. >>: That's what I meant calling the thing. And another thing is so should be probably some way incremental the way that it works because it's easier proving everything when the bug is in the same place over and over. So perhaps [indiscernible]. >>: Turning off the caching. >> Nada Amin: Turned off the caching. Because I wanted to make sure it was signaling all the time. But anyway, that's one thing. So now you know the problem is here. If you look at the stepping function is going to step to the S branch and since we -- if we have something that looks like this, I mean, this used to have type NAT because of the way the wrong function, the wrong typing worked and now it has type two, which is different. So you know there's a problem. So anyway this was just to show some support. I mean, I guess now I have -- it's already 210. So I can discuss a little bit more -- yeah? >>: At the end of it so and exclusivity side what's the [indiscernible] what's like [indiscernible] do you use? >> Nada Amin: So Dafny, for example, doesn't have high order functions, which a big limitation, really, for especially in this kind of setting. But usually you can represent -- so say in COC you would use an environment for things, like a partial function environment. And here you can use a map and things like this. So otherwise in COC you have these relations that allow you to define inductively what your evidence looks like, and in Dafny you can use predicates for this, but it doesn't have quite the same expressivity, especially in terms of like termination and co-induction because co-inductive relations have certain properties and things. But, yeah, I've been able to do quite some fancy systems in Dafny. So one thing, for example, is doing logical relations, it's very hard to do in COC because you have a lot of mutual inductions but in Dafny I can just use a step index and it works quite well. Any more questions? So that's it for the demo part. I thought this example was nice because it shows that Dafny can do a lot of the proving itself, and you can really focus on the interesting case. The way I actually use it in practice is I worked top-down. So I start with the theorem I want to prove and whenever a case gets complicated I make up a lemma for this case and I keep going. And then later I realize, oh, maybe this lemma is too generous, it's never going to hold and I refine it and what's nice is that if the original proof works with the more precise lemma, it still works. It's not like in COC where you create a lemma, the exact form of the lemma really matters for how you're going to use it in the proofs. So what I mean here is that I use an example from my presentation, yeah. So first I thought I needed this lemma which I guess you would need to understand the calculus. But it's basically saying that if you have -- it's basically the sub typing inversion. If you have two paths and their types are sub types of each other and you can get something from P, you should also be able to get something from whether this should be a P prime here. You should get something from P prime and it should be in the sub typing relation. And the problem then is that I found it doesn't hold in my calculus which is strange because you would expect this. Then I realized if I just add the additional rule P reduces to P prime, all my proofs were still going through because in every case Dafny managed to prove that P does reduce to P prime. And then I was able to keep it as it is just by refining the lemma. >>: How do you -- [indiscernible]. >> Nada Amin: So I found that it didn't work, but just looking at it and trying to prove it for a little bit and seeing in which case I got stuck and then I came up with a counterexample. Okay. So any questions about Dafny? So I thought I'd end up by showing how I've been using Dafny in my own research, give a quick introduction to what I've been going on with Martin Ordersky and others at EPF. >>: Could you just show publicly available data. I mean, the proof of -- It's on your page. >> Nada Amin: Yes it's on Get Hub Dafny sandbox. things there, actually. And there are other >>: Thank you. >> Nada Amin: Okay. So what we're trying to do with this dependent object type calculus is capture a core feature of Scala, which is path dependent types. And the goal is really to have this core calculus be what every other Scala type maps to. So we would only have this path-dependent types, extract type members, and we would sync model, Scala's mixture of nominal structural typing, but only refinement types, but then Scala has [indiscernible] types, existential types, we wouldn't treat a model directly in the calculus. We also don't want to model inheritance. These would be expressed by translation to the calculus. And just to give an example, just to give a brief overview of the syntax, what we have is that the types are the most interesting part. This is what we're trying to capture. So we start with a bottom and top type. And then we have these refinement types, which allow you to say that we're extending this type T with a set of declarations and declarations can be values and methods as usual, but also types. And if they're types you specify them by giving a lower bound type and an upper bound type. And because types can have types as members, when you have an object of a certain type, you should be able to refer to these type members, and this is what is done with these path-dependent types. So P dot N means take the type member L from P and that's also a type. >>: Make it concrete, make it like an object bit array and its element of it. >> Nada Amin: Yeah, to make it concrete you can have an animal and it has some type mu which is upper bounded by fluid. So you would say that the lower bound is bottom and the upper bound is food N dot. And you could extend this animal with a cow and you would say that here the meal is just grass. So it's upper bounded and lower bounded by grass. And then you can reason about these things. So if you have an animal you can't really feel anything if all you know about it is an animal. If I could feed an animal, okay, well, meat, then if it's a cow that wouldn't be so good. So and the reason this works in the calculus is that whatever this type is, it has to be a lower bound of A. Meal and you don't really know what A.meal is but you can open it up. And since we're doing sub typing on the right with meal, we open it up by looking at the lower bound. And here we have bottom. So we cannot feed it anything. On the other hand, if we have a cow, we can feed it grass, for the same reason. Yeah, so this is to make it concrete, but really the point is we just have these types of actions and refinement types. So it's pretty minimal. Then we extend it with type intersections and unions in the classical way to get a subtyping lattice. The goal was to really have a minimal set of types and then try to see where we can go from there. One key motivation from Scala was that currently in Scala, it doesn't have these classical intersection and union types when you compute the greatest lower bound and least upper bound things have to be done in an eager fashion and you can get into types that are actually approximated by an infinite sequence. And in that, this would be solved by really just -- I forgot this one. So in dot this would be solved because you would just say, well, we just want the least upper bound of C and D and this is just a type by itself. So we're kind of delaying the problem to when we need to expand this type and look at it. So the calculus itself is -- the syntax is rather simple but in terms of judgment it gets a bit complicated. Like you have the usual type of assignment, subtyping wherefor this. You also have this expansion that allows you to flatten, look out what is really the set of declarations and type, because you could have nested refinements, refinements with intersections, unions and things. And membership which allows you to select a particular declaration from a term. And so if we look at the example where we're looking at a function that has an apply method and we're taking the union with another function within apply method, then in practice what that means is that if we type an application of this function, we need to take the -- this is the type of the function that when we expand it we get this type for the apply method. And so we see that the decomputation is done at the time where you actually need to know -- it's not done at the time where the function, when the type is defined, but at the time where the type is used. So this was just to give you a flavor and for this concrete example of animals, what happens with these bounds is that when we're refining animal we still have to keep this -- we still have to use these bounds from animal and from cow together. So the way we do it is that for the -- for this refinement of animal here, we have this reads that the lower bound is grass or bottom and upper bound is grass or food and that just reduces to grass or grass. So that works fine here. But if instead we just said, okay, mu can just be food with lower bound food. Here we'd get that bound. So we'd get food to grass. And this means in practice it means this type can never be instantiated because when we create a type we check that the bounds are good. >>: Is this global? >> Nada Amin: Yes. And one interesting aspect is that we don't really have a separate class table for things. The denominality really comes in through the path dependent types. Which means that here if I have something that is a poodle, then I know that it's a pet because if it's a poodle, I can open it up and see, okay, I really just need to compare dog to pet and then I can compare pet to pet. So eventually every sub typing rule on path dependent types if there's no structural aspect it reaches a flexivity type part on the chain. Okay. Then I just wanted to give a flavor of the kind of issues we have. So one example is that we need to take path equality into account. Because here there's no need to understand this code in detail but the gist of it is A.I.L reduces to V.L. And V.L has this type that depends on V. And A.I.L has this type A.I.X that depends on A.I. So somehow now we need to be able to relate these two types but on a first approximation they're not equal because A.I.X has a lower bound of bottom which means we can't really compare it to V.X by opening it up. But we know something more. We know that A.I reduces to V, so it it works in this case but that means you're typing all that needs to take path equality into account. >>: The only node here because you write I equals B, being a difference. >> Nada Amin: >>: Exactly if here it was -- It's co-dependent. >> Nada Amin: Well, it's -- it depends on what is in your store. Yeah. I mean, this is only true because A.I reduces to B. If A.I was reducing to B prime it wouldn't be true anymore. >>: Or couldn't [indiscernible] figure out what it reduced to. >> Nada Amin: But that becomes an issue only when you have things in the store. So it's really something that shows when you have preservation. And this is also related to the sub typing inversion, where you can -where you really -- where you really need to add close P reduces to P prime and this lemma for it to actually work. And initially we also had some very strange issues with well formness. One tricky aspect you have intersections that are somewhat delayed because something looks fine. So if you just look at the type over here down here it looks fine by itself. And it's only when X.L is refined to be this type here that you have a problem. And the problem is that if you look at the red types by themselves, then you have that B refers to A and then here A refers to B. So there's like a cyclic dependency between them and somehow if you try to ensure -- depending on your well formness rules you might get stuck in the most precise type and not in the previous situation. So that's just to give a flavor. I mean, in summary what we've been doing is really actually using Dafny to help guide the design of the calculus also and figure out what do we really need for preservation to hold. And we're also looking at alternatives using logical relations and big steps semantics for this calculus. So that's it. Any questions? [applause] >>: So have you represented some of the rules in this language in Dafny already on slide 6. >> Nada Amin: Yeah. Yeah, so I have the -- so this one is a very big development actually. So it probably doesn't completely time out in the ID. But it doesn't completely like -- there's some timeouts in the ID when you run it. But the gist of it is you have this -- I'm going to remove the other things. So the main thing is we have typing for paths and the typing also takes the store in context and returns the type for the path. And here I'm using what Mikel mentioned before I'm using the predicate approach not the function approach. And I'm also always using a step index so whenever I have any recursive call I'm just decreasing the step index which allows me to really do mutual induction proofs easily just based on that. And then -- and then we have like all sorts of other things like well formed declarations and everything. Well formed type. Then you can see, for example, this membership and rule is not very constructive. It just says, well, I mean it's using existentials a lot and things like this. So you can do that sort of thing as well. >>: So about the end, in COC a lot of times people will define things like typing as data types. And then you can do induction on those data types. >> Nada Amin: Yeah. >>: But do you find that using this natural number is a better way to do that induction or -- >> Nada Amin: So I missed a little bit being able to do inductive evidence like kind of data types in the prop world in COC, but on the other hand, in COC mentioned induction is quite tricky. Sure it does some part of it automatically for you. But then you have to do a lot of work to get it started, right? And here I have so many judgments that using the step index is just so much easier. Like Dafny can always say this is decreasing and then I can do my proofs. Of course, the catch is that if I have a sort of unintended cyclic dependency which means for some derivation it always goes to zero, then that's not so great. But I need to watch out for this. But in general it's been rather nice to do that. Like just to show also one thing I didn't really do too much because I'm using the step index I need to show things are monotonic. If you increase the step index, you still get the same types. And so there's these ghost lemmas that do this. And this I mean I didn't bother to prove them. Like some of them I just assumed for now and keep going with this. Okay. So I guess it's ->>: Question. I mean this is really awesome. I really like it. for the moment I'm going to play the role of a grumpy COC person. >>: But Just say Frenchman. >>: You know, a criticism that such a person may raise is that type systems are inherently these constructive things that you work with that you get nice constructive proofs out of COC and you can interpret COC theorems and the constructions and stuff. What can you say here? >> Nada Amin: Yeah, that's -- I mean, well, hopefully I guess you're getting to maybe having a verified core of Dafny. But, I don't know, for me it's just really -- right now my concern is really, okay, I'm doing this research calculus. Can I -- how do I get some guidance on proving it's sound when there's so many hairy issues. And I find that doing things in Dafny allows me to focus on the big picture. I mean, eventually maybe it's not convincing to everyone. But for me it focuses on the big picture. I can really -- I don't need to do this low level manipulation to get the exact proof term that I need for something. But I mean under the hood I think if Z 3 is sound, then things are fine, right? >>: Question. >> Nada Amin: One of the classical constructor stuff. Yeah. >>: I guess. I guess maybe one way I might look at it is to say, look, there's a community of people doing time proofs. There's a community of people these days who do meta theory in COC. And maybe this is sort of somewhere in the middle you don't necessarily get the tiny TCP but you may get the COC. But certainly it's way better than a hand proof. Maybe we don't need like micro-TCP [indiscernible]. >> Nada Amin: And I think especially for teaching, Dafny has a lot of potential, because the way it does induction is very natural. So even just learning these concepts, it would be much easier in Dafny than in COC where you have to learn the machinery and the stepping curve is really high. Dafny uses some concepts that you already kind of understand which is contracts. And bootstraps from there to do more serious proving. >>: Is there any way to get Dafny [indiscernible] it's generally in these proofs where you have the empty code basis. But it's excluded. >> Nada Amin: >>: I don't know. Black box. >> Nada Amin: I mean, one thing you can do is you can also -- if you really want to -- so it depends why you're doing the proof, right? If you really want to -- if you're doing it as a beginner student trying to understand progress it's not so helpful it's just saying, well, that's done. So one thing you can do is really do say here induction false, and then yourself try to do the steps manually. And I mean in this case it wouldn't be so hard. It would still help you with other aspects. But there's a way to try to get more insights. >>: One way to think about it is that if this is saving human time to do the proofs in the first place, then if you are really wondering about -- is it the sound proof, then one could imagine that one would take the proofs that Z3 constructs, map them back to -- first of all, generate those proofs, and then map that back to the GUI level and then to the Dafny level. That would be a large project to do. But I mean some people like doing that. a lot of people, could be nothing. And if it would mean a lot to >>: I guess I just was wondering if there was some way to get the proof in a format that's verifiable by something that's not verifiable. >>: Right. >>: Z-3. >>: But it's a notion of what a proof is then it needs to be manipulated and fed to something else that would then -- you want independent verification. And so it's possible, but it's a big project. Because Z-3 still does its proofs very big steps. It's as I think ->>: Compared to some other things. >>: Right. >>: If somebody could -- >>: Compared to what you're using as the checker. >>: And one could also mention that such a project, such a project would be a very large one. You started with something that like in these examples you use functions and data types. Maybe there's a more direct translation of these proofs and the input to let's say Isabel or something or would call for that matter. >>: Nothing's there. >>: But I guess you didn't show it here, the calc statement. Sometimes when you write the proofs yourselves, instead of having just the certs and calls out to lemmas, you can use verified calculations. And those are like human default. >> Nada Amin: Yeah, there was just one trick like regarding the capture avoiding substitution. So you can do a renaming like here. Well, this is for like type substitution, but it's the same thing. But the problem then is that the decreasing cloud is a bit -- you need to decrease on the size of your data type instead of the actual structural look of the data type. But you can also do this in Dafny quite easily by defining your own decreasing measures and things. Okay. >>: Deeply impressive. >>: So now she's here until the end of the week. So if you want to pick parts of her brain, let me know, or if you want to show her the related things, whatever that might be. [applause] >> Nada Amin: Thank you.