Dafny export clause in a module - module

module A {
export S reveals f
export M provides g
function f (x:int):int
{x+1}
function g (x:int):int
{x-1}
}
module B {
import opened A`{S,M}
//export K reveals k
//export K provides k
function k (x:int):int
requires f(x) == 0
{x*2}
}
Activating any of the commented export clauses in module B makes the imported function f to be unknown for module B. Some help?

The error message is a bit confusing, or at least subtle. Uncommenting either of the two export K ... declarations produces the following two errors:
This export set is not consistent: K
Raised while checking export set K: unresolved identifier: f
Let me explain. I will focus on the export K provides k declaration; the other is similar.
By declaring an export set, a module makes available a subset of its declarations to the module's importers. The provides clause puts the "signature" of a declaration into the export set, and a reveals clause puts both the "signature" and the "body" of the declaration into the export set. For a function, the "signature" of the declaration includes the function's type signature as well as the function's specification. So, the provides k clause in your example essentially says to export the following portion of the declaration of k:
function k (x:int):int requires f(x) == 0
The relevant thing to notice here is that this portion of the declaration also mentions f. (This is also true for the export declaration with reveal k.)
An export set has to be self consistent. This means that everything mentioned in the exported declarations (more precisely, the exported portions--"signature" or "signature + body"--of the exported declarations) must make sense separately. In particular, this means that every symbol that is mentioned in the portions that are exported (here, the mention of f in the precondition of k) must also be part of the export set.
So, the problem is that you're trying to export k but not f. If f were declared in module B, you would know what to do: just add f to a provides clause of your export set. But in your case, f is declared in module A, not in B. This seems like a problem, because an export set in module B is only allowed to export symbols defined in B.
The problem has a simple solution. To explain it more clearly, let me temporarily change your module B a little:
module B {
import A = A`S
export K provides k
function k (x:int):int requires A.f(x) == 0 {x*2}
}
Here, I'm importing only A`S (not A`M), I'm explicitly showing the local name for A`S (namely, A), and I have omitted the opened keyword. Since I omitted the opened keyword, I also had to qualify the mention of f in k's specification (writing A.f instead of just f).
Okay, in this module B, export set K is still not consistent, because it tries to provide k without providing A.f. More precisely, the second error message now says that A is unresolved. This is good, because (the local name) A is declared in B, which means we can export it. To solve this problem, simply add provides A to the export set:
export K provides k, A
This makes export set K consistent, because every symbol mentioned in the ("signature" portion of the) declaration of k is visible. It is not necessary for K to export f directly, because f is mentioned by .f as a member of A, and A is exported.
Let's work our way back to your example, in four steps.
As a first step, let's change my import declaration to import both of A's export sets, S and M:
import A = A`{S,M}
Here, I'm still showing the local name A explicitly.
As a second step, let's add back the opened keyword:
import opened A = A`{S,M}
This makes it possible to refer to the imported declarations either as qualified (like A.f) or as unqualified (just f).
As a third step, let's make use of the fact that, inside B, we can refer to f as unqualified:
function k (x:int):int requires f(x) == 0 {x*2}
As a fourth and final step to get back to your example, let's omit the explicit local name A in the import declaration. The default local name is the same as the module being imported, namely A. Now, we have the following error-free program:
module B {
import opened A`{S,M}
export K provides k, A
function k (x:int):int requires f(x) == 0 {x*2}
}
I hope this helps.
Rustan

Related

using multiple-dispatch for functions when they are defined in different modules (Julia)

I tried to use multiple-dispatch for functions that are defined in different modules in Julia, e.g.:
module A
export f
f(i::Integer) = println(i)
end
module B
export f
f(i::AbstractFloat) = println(i)
end
using .A, .B
f(.1)
But it returns an error
WARNING: both B and A export "f"; uses of it in module Main must be qualified
ERROR: LoadError: UndefVarError: f not defined
I understand that julia tries to avoid name conflicts in different modules. But in my case these f functions can be distinguished by their arguments but it still returns an error. In the docs, Julia offers three ways to solve the problem:
Simply proceed with qualified names like A.f and B.f. This makes the
context clear to the reader of your code, especially if f just happens
to coincide but has different meaning in various packages. For
example, degree has various uses in mathematics, the natural sciences,
and in everyday life, and these meanings should be kept separate.
Use the as keyword above to rename one or both identifiers, eg
julia> using .A: f as f
julia> using .B: f as g
would make B.f available as g. Here, we are assuming that you did not
use using A before, which would have brought f into the namespace.
When the names in question do share a meaning, it is common for one
module to import it from another, or have a lightweight “base” package
with the sole function of defining an interface like this, which can
be used by other packages. It is conventional to have such package
names end in ...Base (which has nothing to do with Julia's Base
module).
For the first two solutions, they can't solve my problem since I really need to display multiple-dispatch and they have to be defined in different modules, and I don't understand the 3rd solution. Could someone help me please?
function f() end
module A
export f
Main.f(i::Integer) = println(i)
end
module B
export f
Main.f(i::AbstractFloat) = println(i)
end
using .A, .B
f(.1)
Basically, make them the same function by defining a "prototype" function outside both of them and specialize that function twice in each submodule. Here because module A and B lives in global scope so I used Main., you should use whatever is housing your sub modules

How to import theorems from Coq.Numbers.NatInt.NZDiv?

In this doc link there are useful theorems about division. I tried importing it using Require Import in CoqIDE 8.9.0, however while the import succeeds, the following code fails with The reference div_lt_upper_bound was not found in the current environment.
Require Import Coq.Numbers.NatInt.NZDiv.
Check div_lt_upper_bound.
I tried downloading the source code for the file and manually importing it via Load, but then I get the following message with no further explanation (the first line is in red):
Application of a functor with too few arguments.
Interactive Module Type DivMod started
div is declared
modulo is declared
Module Type DivMod is defined
Interactive Module Type DivModNotation started
Module Type DivModNotation is defined
Module Type DivMod' is defined
Interactive Module Type NZDivSpec started
div_mod is declared
mod_bound_pos is declared
Module Type NZDivSpec is defined
Module Type NZDiv is defined
How do I load those theorems properly? Why did the previous methods not work?
The quick answer is that you are looking at the Module Type (see Print NZDivProp.).
The actual usage is simple, e. g.
Require Import Arith.
Check Nat.div_lt_upper_bound.
(*
Nat.div_lt_upper_bound
: forall a b q : nat, b <> 0 -> a < b * q -> a / b < q
*)

Can I import just one declaration from an F# module?

Suppose I have a module like this:
module Foo
let x = 1
let y = 2
Now I can use this module like this:
module Bar
let z = Foo.x + Foo.y
Is it possible to import a definition from Foo such that it does not need to be qualified?
Something like:
module Bar
import x from Foo // Not real code
let z = x + Foo.y // x need not be qualified
Note that I do not want to import everything from Foo
You cannot, there is no direct F# equivalent to the ES6 import { ... } from 'Module' syntax. F# supports organizing code into both modules and namespaces, but both modules and namespaces are 'imported' in their entirety with the open keyword. As mentioned in the comments, you can use local bindings to simplify qualified access to values (such as let exchangeRange = Conversions.Currency.UsdToCadExchangeRate) or type aliases to simplify qualified access to types (type Converter = Conversions.Currency.CurrencyConverter).
In addition, modules can be marked with the [<AutoOpen>] attribute to make their contents accessible without qualified access, or the [<RequireQualifiedAccess>] attribute to make their contents accessible only when qualified, even if the module is referenced in an open expression.
See this MSDN article for more information.

Import module into current scope?

The modules have very long names (they make names of the imported functions three times longer then needed), for example: mapconcat looks Project.Utils.mapconcat is there any way to import this function and use it w/o fully qualifying it by the module name?
You can always do :
var x = Project.Utils.mapconcat;
// now use x in place of mapconcat
PS: you can use the import statement to create an alias for a module
import pu = Project.Utils;
// now:
pu.mapconcat
This is assuming Utils is a module name (and not a class).

Data.Vector.Binary overlaps Binary [a] instance

In my application I need to serialize a vector containing an arbitrary datatype, in this case is a list of Doubles. For serializing the vector I'm importing Data.Vector.Binary.
When loading the module in GHCi the following error arises:
Overlapping instances for Binary [Double]
arising from a use of `decode' at Statistics.hs:57:33-42
Matching instances:
instance (Data.Vector.Generic.Base.Vector v a, Binary a) =>
Binary (v a)
-- Defined in Data.Vector.Binary
instance (Binary a) => Binary [a] -- Defined in Data.Binary
Is the list an instance of Vector?
I looked through the documentation but could not find such instance.
What can I do to be able to serialize this structure?
Edit:
I'm using the following package versions:
vector-0.6.0.2
vector-binary-instances-0.1.2
binary-0.5.0.2
Also here is a snippet that shows the issue, this time with a list of chars:
import Data.Binary
import Data.Vector.Binary
import qualified Data.ByteString.Lazy as L
main = L.writeFile "/tmp/aaa" $ encode "hello"
Ok, I think I see the problem here. The vector-binary-instances package defines:
instance (Data.Vector.Generic.Base.Vector v a, Binary a) => Binary (v a)
which is very bad. This definition means "for any type 'v a', this is a valid Binary instance". That means this instance is available for any type that matches v a. That includes (but is not limited to) all lists, all functors, and all monads. As a demonstration, ghci reports the following:
Prelude Data.Binary Data.Vector.Binary Data.ByteString.Lazy> :t getChar
getChar :: IO Char
Prelude Data.Binary Data.Vector.Binary Data.ByteString.Lazy> encode getChar
<interactive>:1:0:
No instance for (Data.Vector.Generic.Base.Vector IO Char)
arising from a use of `encode' at <interactive>:1:0-13
Possible fix:
add an instance declaration for
(Data.Vector.Generic.Base.Vector IO Char)
In the expression: encode getChar
In the definition of `it': it = encode getChar
Here the interpreter is attempting to use this instance for getChar :: IO Char, which is obviously wrong.
Short answer: don't use vector-binary-instances for now. This instance is broken, and given how instances propagate through Haskell code it will cause problems. Until this is fixed, you should write your own binary instances for vectors. You should be able to copy the code from vector-binary-instances and restrict it to a monomorphic vector type
instance (Binary a) => Binary (Vector a) where
I believe this will work with any Vector which is an instance of Data.Vector.Generic.Vector.
You also may want to contact the vector-binary-instances maintainer about this.