-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Teach the typechecker more about exponents #704
Comments
I don't know how difficult this would be, but it would really be nice if the typechecker knew that |
Another thing we might teach Cryptol about exponents is injectivity: |
We may want to use the kind of normalization that Clash does, something like what this package does: http://hackage.haskell.org/package/ghc-typelits-natnormalise |
I was recently annoyed that cryptol could not deduce that |
FWIW, I tried adding the following axiom and a couple of variations to the typechecking database, and it seemed to cause an instantiation loop. We might still be able to do something here inside Cryptol itself, but just adding axioms to Z3 doesn't seem to work very well.
|
Do you need >y 0 and >z 0? Surely this rule applies when they are 0 (or indeed when they are negative, but obviously negative exponents might not be defined). I assume this isn't causing your issue though. |
Yeah, I don't think it's relevant to the issue of Z3 getting lost in the woods with this axiom. I don't have much experience with Z3's pattern triggering mechanism, so it's possible I messed something up, but I could not figure out how to get this to behave well. |
I have actually managed to sort some of my previous issues with recursion - or rather, I've reduced it to the above problem. But I now need to implement the following...
But I can't work out a way to do even the reduce pair with the tools available: Cryptol doesn't know anything about inequalities and powers, even, so one can't even use |
Humm... I also don't see any obvious way to witness these equivalences with the tricks currently at our disposal. I wonder about allowing the following escape hatch for these kinds of size equivalences that we can't prove.
With the semantics that the function is a no-op at runtime if |
@robdockins I like the |
These do it (or in the special case...):
Your solution is nicer, though. As yav says, it's "more honest". |
I have managed to get my code to work using my powAdd and powAddRev functions (powAddRev |
This does you the job of coerceSize, I think. Edit: actually, this might be even better:
(not sure). Edit2: or this!
|
That works, but I think it's desirable for efficiency reasons to make it a primitive. |
Yeah, that makes sense. Using coerceSize, then, here's a rewrite of that sorting algorithm you added recently:
So it's a nice way of doing this sort of pattern, I think? |
I have found (and been told by new students of Cryptol) that they find it hard to grasp why Cryptol won't allow them to write something like this (nonsensical example):
This kind of pattern shows up in many different crypto algorithms such as Salsa20 (Salsa20Expansion), HMAC (kinit), and NIST-800-38F (KW and KWP). The solution being presented here is something along the lines of:
Consider going a step farther -- what would it look like for The concatenation with |
Rereading my comment, I think what I'm suggesting (and to a lesser extent what |
Certainly the concatenation with undefined was designed to achieve exactly that (in my head it is somewhat analogous to accessing a C-style array outside of its initialised bounds). I think this issue is trying to solve this kind of problem/pattern in general: #701 - it avoids the hack of, effectively as you say, doing typechecks at runtime. That being said: it wouldn't solve the issue of the typechecker not understanding exponential arithmetic (in a sense they are different but enmeshed issues both of which coerceSize solves). Note that coerceSize actually can be used for when m is not equal to n, as it is currently written, and as long as you then don't try to actually ultimately output any junk data, it'll be fine (or it just truncates). It doesn't act on double arrays, of course, but one can just use |
The version I had in mind is morally equivalent to:
Modulo the fact that Cryptol won't accept this definition without I certainly don't think we should be inserting these coercions automatically; the whole point is to only allow things that the user is very confident are correct but that the typechecker cannot prove for one reason or another. |
I appreciate the assert! That's a nice way to stop accidental truncation. |
@robdockins If the type system could demote type constraints to
I've stumbled into the forced
Would it be feasible to support this type of thing? If so, I can create an issue for it. Then we could do:
And
|
That's an interesting idea. I think demoting all constraints would probably be a little tricky (class constraint resolution is sort of three-valued), but we can certainly add one or more primitives specifically for computing values corresponding to type-level comparisons. I'm imagining something like:
Those should be pretty simple to implement, and would let us do things like you've sketched above. We could maybe even add magic backtick support for desugaring exactly those constraints, as we currently do for I think that would work, and I like it better than just making a special case for |
On second thought, we wanted |
These allow users to test equalites between type variables and branch on the results. This could nearly be accomplished by instead demoting the value of the numeric expressions to integers and comparing them as integers. However, this required `fin` constraints on the expressions, which is sometimes undesirable. We also implement the `coerceSize` operation discussed in issue #704. We may decide to make this a primitive at a later time.
@weaversa asked:
Well, that specific problem is not so hard to solve; using
Now Cryptol is perfectly happy:
I admit, though, that this smells like a hack rather than some generic easy-to-use method. Demotion to Bit sure seems more general. |
Regarding some kind of binary view - one thing I have encountered is having to add the explicit hint of 2 * 2 ^^ k == 2 ^^ (1 + k) into algorithms that work on types of size [2^^k] by splitting; it would be good if the typechecker could deal with powers of 2, at least, in this manner automatically: I don't know if this needs its own issue or might naturally be solved as part of this?
Originally posted by @linesthatinterlace in #701 (comment)
The text was updated successfully, but these errors were encountered: