I'd like to put the definition of a top-level Agda module and a local anonymous module using it in the same file. However, the top-level module has parameters, and I'd like to instantiate it in the second module.
So basically I would like to do something like this:
module MyModule (A : Set) where
foo : A -> A
foo x = x
module _ where
open import Data.Bool
open MyModule Bool
bar = foo true
However, the open MyModule Bool line fails with "The module MyModule is not parameterized, but is being applied to arguments".
Is there a way to do this without:
putting the second module in a separate file
indenting the contents of MyModule, i.e. something like
module _ where
module MyModule (A : Set) where
foo : A -> A
foo x = x
module _ where
open import Data.Bool
open MyModule Bool
bar = foo true
?
The precise thing you're asking for is currently not possible in Agda. The closest thing I can think of is the following:
module MyModule where
module Main (A : Set) where
foo : A -> A
foo x = x
private
module _ where
open import Data.Bool
open Main Bool
bar = foo true
open Main public
This will expose the contents of the main module in their generic form while hiding the private definition bar from other modules. However, when you import the module and want to instantiate the parameter, you cannot write open import MyModule Nat directly, you'd have to instead write
import MyModule using (module Main)
open MyModule.Main Nat
(for importing the generic version, open import MyModule would work just fine).
Related
I have a module defined in a file. This Module1 defines a struct and a function that I'm using in my main script. I include this module within another Parent module with include("module1.jl") so that Parent module can use the struct and function in module1. However, I'm having problems with the namespace. Here's an example in a single file:
#this would be the content of module.jl
module Module1
struct StructMod1
end
export StructMod1
function fit(s::StructMod1)
end
export fit
end
module Parent
#including the module with include("Module1.jl")
module Module1
struct StructMod1
end
export StructMod1
function fit(s::StructMod1)
end
export fit
end
#including the exports from the module
using .Module1
function test(s::StructMod1)
fit(s)
end
export test
end
using .Parent, .Module1
s = StructMod1
test(s)
ERROR: LoadError: MethodError: no method matching test(::Type{StructMod1})
Closest candidates are:
test(::Main.Parent.Module1.StructMod1)
If I remove the mode inclusion in Parent and use Using ..Module1 so that it loads from the enclosing scope, I get this error
ERROR: LoadError: MethodError: no method matching test(::Type{StructMod1})
Closest candidates are:
test(::StructMod1) at ...
In your example, s is a type object not an object of the type StructMod1. In order for s to be the latter, you need to call the constructor for that type. So you should write s = StructMod1() instead of s = StructMod1.
You can read more about types as first class objects here.
Given the following module declaration:
module ( myinterface.mymodport mybus, ... );
And assuming that myinterface has parameters, how do I specify them?
The interface instantiation happens only in the testbench, but now I want to synthesize the DUT, so the TB disappears.
This is an oversight in the SystemVerilog LRM. There's no syntax to specify a required set of parameters for an interface in a module header.
You might check your synthesis tool to see if they provide any way of specifying parameter overrides for the top-level synthesis instance.
You specify the parameter when you instantiate the interface; you do not specify it in the port list of the module. Given
interface myinterface #(parameter DATA_SIZE = 0);
...
All you need is
module mymodule (myinterface.mymodport mybus);
...
because somewhere else you have
myinterface #(.DATA_SIZE(64)) i();
interface myinterface #(parameter DATA_SIZE = 0);
logic [DATA_SIZE-1:0] AWID;
logic [31:0] AWADDR;
modport mymodport (input AWID, AWADDR);
endinterface
module mymodule (myinterface.mymodport mybus);
initial
$display("mymodule");
endmodule
module top;
myinterface #(.DATA_SIZE(64)) i();
mymodule m (.mybus(i));
endmodule
https://www.edaplayground.com/x/528x
I have a record where two fields should be 0 when the record is initialized, and only updated by the internal functions.
How can I accomplish this? Where do I keep internal state? Ask the user to please supply 0 as the arguments and not touch those fields?
You can limit the types and functions a module exposes by using the exposing keyword on the module. However, you cannot hide individual fields of a record type. Let's first define the record alias that you want to keep private:
type alias InternalModel =
{ foo : Int
, bar : Int
}
First off, we need a way to hide the internals of a value. This is typically done by exposing a type but no constructors.
module MyModule exposing (Model)
type Model = Model InternalModel
The above code will not let external modules see or interact with the InternalModel type parameter at all. You can't even create a Model outside of this module. This is where we can define a function that creates a new Model and sets those initial values to zero. You will also have to adjust the module exposing list (here I'll let the external module set bar on creation, while defaulting foo to zero):
module MyModule exposing (Model, newModel)
newModel : Int -> Model
newModel bar =
Model { foo = 0, bar = bar }
If you want to expose "getters" and "setters" for fields, you can do so like this:
module MyModule exposing (Model, newModel, getFoo, setFoo)
getFoo : Model -> Int
getFoo (Model {foo}) =
foo
setFoo : Int -> Model -> Model
setFoo foo (Model model) =
Model { model | foo = foo }
In TypeScript I can define a global/top-level namespace and use it in another file like so:
namespace foo.blah {
export function baz() {
console.log('hello');
}
}
And in another file, this works:
foo.blah.baz();
However, if I then import something from another module:
import Thing from 'boo';
namespace foo.blah {
export function baz() {
console.log('hello');
}
}
Suddenly my whole file is a module, the foo.blah namespace is local, not global, and the foo.blah.baz() call in the other file fails. export namespace ... just causes the namespace to become part of the module's export, not a global.
Is there a way to write a TypeScript file which imports from other modules but also defines global/top-level symbols?
At the moment I'm doing this:
import Thing from 'boo';
import * as $ from 'jquery';
namespace foo.blah {
export function baz() {
console.log('hello');
}
}
$.extend(true, window, {foo});
Which works, but the TypeScript compiler still can't see that foo.blah... exists as a global in other files.
(The file is the entry point for Webpack, and I'm trying to import things from other modules in the Webpack bundle and assign them to globals so they can be used in <script> tags on the page.)
When you add the import, you switch from internal modules to external ones, as the spec says:
In external modules, relationships between files are specified in
terms of imports and exports at the file level. In TypeScript, any
file containing a top-level import or export is considered an external
module.
http://www.typescriptlang.org/Handbook#modules-going-external
The philosophy behind external modules is to avoid global objects, why don't you create a new module with foo.blah (and all the stuff you need) and import it as TypeScript expects it?
The solution is to declare namespace in global.
declare global {
namespace foo.blah {
function baz() {
console.log('hello');
}
}
}
create a global.d.ts and put your type there
reference: cannot use d.ts file to load declaration merging
For me, the problem was to call the google-one-tap library from a module. The library is only available as script, but a types package exists: #types/google-one-tap.
Code snippet from the types package #types/google-one-tap/index.d.ts:
export as namespace google;
export const accounts: accounts;
export interface accounts {
id: {
initialize: (idConfiguration: IdConfiguration) => void;
disableAutoSelect: () => void;
[...]
As you can see in the above declarations file, there is a namespace google that contains objects/interfaces.
My code calling the library from a module:
google.accounts.id.initialize(...)
Without the fix (see below) the above code returns an exception when building: error TS2686: 'google' refers to a UMD global, but the current file is a module. Consider adding an import instead.
To be able to see the types and to get successful compilation, I declared a variable for the namespace google as follows. There is no code generated for declarations.
declare var google: {
accounts: google.accounts
};
// Now this works without errors.
google.accounts.id.initialize(...)
All of this is actually not recommended and red flags per documentation. Moreover it says that:
Multiple files that have the same export namespace Foo { at top-level (don’t think that these are going to combine into one Foo!)
That being said, I also had to preserve namespaced construct when migrating to ES6 modules because some systems don't offer a simple way to suddenly change namespace references like find & replace (MS Power Apps for example) or maybe you are really developing a library and want to preserve the entry point foo
If you had different first part of namespace per file, this would be enought:
(window as any).foo = foo
But having multiple, each file would overwrite previous window.foo
But there are ways what you can do when migrating to modules. With some webpack configuration, namespaces CAN be exposed as a public variables.
/*
Merge foonamespace between multiple files and expose it as a global variable. Otherwise foo namespace stays as module scoped variable.
exports global variable foo (because library.name is foo), and it uses a construct that:
- Copy the return value to a target object if it exists, otherwise create the target object first: Basically copies foo.* to foo object. This turns out to be a merge of namespaces.
- Namespace MUST BE exported.
- export: 'foo' means that instead of having global variable foo.foo.blah I have foo.blah (basically this should be the value whatever namespace starts with)
*/
output: {
...
library: {
name: 'foo', //or [name] if you have namespace same as entry point name
type: 'assign-properties' //or var or window if same namespace doesn't span multiple modules
export: 'foo'
},
}
There are many more ways to expose stuff to global scope (different type values available). Refer to webpack documentation
P.S. A module (having import or export statement) means variables get scoped as a module (rightly so) and that brings these challenges in the first place to preserve namespaced construct. Reference
Modules are executed within their own scope, not in the global scope; this means that variables, functions, classes, etc. declared in a module are not visible outside the module
P.S.2 How does webpack achieve it? The output looks something like:
var __webpack_export_target__ = (foo = typeof foo === "undefined" ? {} : foo);
var __webpack_exports_export__ = __webpack_exports__.foo;
for(var i in __webpack_exports_export__) __webpack_export_target__[i] = __webpack_exports_export__[i];
if(__webpack_exports_export__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true });
Implication is second level namespace must be unique.
If I run the following code everything compiles and runs fine:
package main
import "fmt"
type Point struct {
x, y int
}
func (p *Point) init() bool {
p.x = 5
p.y = 10
return true
}
func main() {
point := Point{}
point.init()
fmt.Println(point)
}
But when I move the Point struct to a package in the $GOPATH directory then I get the following error: point.init undefined (cannot refer to unexported field or method class.(*Point)."".init)
Can anyone explain to me why this happens?
Once I put the Point struct in a package called class the code looks as follows (the error is on the 8th line where I call the init method):
package main
import "fmt"
import "class"
func main() {
point := class.Point{}
point.init()
fmt.Println(point)
}
Rename init() to Init() should work!
Basically, all the things(function, method, struct, variable) that not start with an Unicode upper case letter will just visible inside their package!
You need to read more from the language spec here:
http://golang.org/ref/spec#Exported_identifiers
Relevant bit:
An identifier may be exported to permit access to it from another package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
the identifier is declared in the package block or it is a field name or method name.
All other identifiers are not exported.
Only functions/methods that have the first letter of their name capitalized are exported
http://golang.org/doc/effective_go.html#commentary
Every exported (capitalized) name in a program...
When I changed init to Init everything worked.