module name and Path in haskell - haskell

I have
root/Main.hs :
import ADT.Stack
main :: IO ()
main =
putStrLn "Hi"
root/ADT/Stack.hs
module Stack (Stack, empty, isEmpty, push, top, pop) where
...
Upon loading Main.hs, I have the error
File name does not match module name: …
Saw: ‘Stack’
Expected: ‘ADT.Stack’
If I change the module name to ADT.Stack in Stack.hs, I can get rid of the error.
However, I dont understand the reason behind such constraint.
Is there no way to avoid specifying in the code of Stack.hs what is already encoded in the name of the directory in which it is contained ?
If there are no alternative way, is there any good reason this ?

If you're using the hierarchical namespaces, your module names should reflect the full path. So, in root/ADT/Stack.hs, you should have
module ADT.Stack (Stack, empty, isEmpty, push, top, pop) where
After that, as you have observed, everything should be fine.
I am not aware of any possibility to derive the module name not only from the name you give it in the file, but also on the location of the file. (That is what you are after, aren't you?) Of course, this should be possible with some fancy preprocessing, but you probably don't want to go there.
So, then, why are things like they are? Not sure whether, for you, it qualifies as a good reason, but one can argue that this scheme has as an advantage that by simply moving a file to another directory you don't silently break any client codes. Instead, you get an error already when compiling the moved file.
The redundancy in the file location and the module name allows processors to find imported modules with only a minimal set of "search paths". Also, it provides a standard for organising source files over larger projects.

Related

Python Modules Replacing Themselves During Load

I've come across some code recently that uses a trick that makes me rather nervous. The system I'm looking at has a Python extension Moo.so file stored outside the path and the developer wants to import it with just import Moo. For various reasons neither the file location nor sys.path can be changed, and the extension must be loaded with ExtensionFileLoader anyway.
So what has been done is to have a Moo.py in the path that loads the extension module and then replaces itself in sys.modules with the extension module, along the following lines:
' Moo.py '
from importlib.machinery import ExtensionFileLoader
loader = ExtensionFileLoader('AnotherNameForMoo', '/path/to/Moo.so')
module = loader.load_module()
sys.modules['Moo'] = module
Now this does actually work. (I have some tests of it in rather gory detail in this repo if you want to have a look.) It appears that, at least in CPython 3.4 through 3.7, import Moo does not bind to Moo the module that it loaded and put into sys.modules['Moo'], but instead binds the current value of sys.modules['Moo'] after the module's top-level script returns, regardless of whether or not that's what it originally put in there.
I can't find anything in any Python documentation that indicates that this is required behaviour rather than just an accident of implementation.
How safe is this? What are other ways that one might try to achieve a similar "bootstrap" effect?

What is supposed to be in __init__.py

I am trying to create a Python package. You can have a look at my awful attempt here.
I have a module called imguralbum.py. It lives in a directory called ImgurAlbumDownloader which I understand is the name of the package -- in terms of what you type in an import statement, e.g.
import ImgurAlbumDownloader
My module contains two classes ImgurAlbumDownloader and ImgurAlbumException. I need to be able to use both of these classes in another module (script). However, I cannot for the life of me work out what I am supposed to put in my __init__.py file to make this so. I realize that this duplicates a lot of previously answered questions, but the advice seems very conflicting.
I still have to figure out why (I have some ideas), but this is now working:
from ImgurAlbumDownloader.imguralbum import ImgurAlbumDownloader, ImgurAlbumException
The trick was adding the package name to the module name.
It sure sounds to me like you don't actually want a package. It's OK to just use a single module, if your code just does one main thing and all its parts are closely related. Packages are useful when you have distinct parts of your code that might not all be needed at the same time, or when you have so much code that a single module would be very large and hard to find things in.

Lua: what scope do variables in "required" modules go to?

After spending the week learning Lua, I was a bit shocked to encounter this weird scenario, since I had previously imagined that the "require" command worked just like a #include in C/C++ (i.e., it's copy/pasted in by the preprocessor).
Obviously that's not the case.
Here's what stumped me:
-- a.lua
this_is_global = "I'm a global var!!"
require "b"
print(global_in_b) -- error??!! globals in b aren't truly global?
-- b.lua
print(this_is_global) -- prints "I'm a global var!"
-- so b can see globals from a
global_in_b = "Am I global too?"
For productivity reasons I've just been creating my own table to act as a scope in b, adding everything I want to access to that table, and then returning the table in b so that I can write:
-- a.lua
stuff_from_b = require "b"
print(stuff_from_b.global_in_b) -- does what we want, in a weird way
I know I can also manually add stuff in b.lua to the _G table to force them to be global, but that feels ugly.
So my questions:
What's exactly happening with "globals" in required files? What table do they end up in if not _G?
What're the commonly accepted ways of accessing scopes of required files?
Neither require nor dofile are equivalent to include: both run code at run time, not textually add source code during compilation.
The globals that a required file sees are the same as the globals in the file that required it.
To avoid pollution and to allow privacy and hiding, it is good practice that Lua modules create and return a table with what they want to export to the external world. It is up to the designer of the module to decide what can be seen from the outside.

Is it possible to hide specific functions from appearing in the documentation using haddock?

I use haddock and don't want all of my exported functions to be displayed in the documentation. Is it possible to hide specific functions?
I found the prune attribute at http://www.haskell.org/haddock/doc/html/module-attributes.html, but this is not what I want since some functions which shall be exported don't have a documentation annotation.
Assuming your current module is Foo.Bar, one solution would be to break it up into Foo.Bar and Foo.Bar.Internal. You could move all the definitions related to the function you don't want to export--perhaps even all the definitions--into Foo.Bar.Internal. Then, in Foo.Bar, you would re-export only the definitions you want the world to see.
This approach has a couple of advantages. It lets you export everything you need, while still giving the user a clear sign that certain things shouldn't be used. It also lets you document your special functions inside the Internal module, which is going to be useful (if only for your future self :P).
You could simply not export Foo.Bar.Internal in your .cabal file, hiding it from the world. However, this is not necessarily the best approach; look at the answers to How, why and when to use the ".Internal" modules pattern?, in particular luqui's.
Another possibility is to make a module Foo.Bar.Hidden exporting all of the stuff you want to hide, and then re-export the whole Foo.Bar.Hidden module from Foo.Bar:
module Foo.Bar (
blah1,
blah2,
blah3,
module Foo.Bar.Hidden
)
where
import Foo.Bar.Hidden
blah1 = ...
blah2 = ...
blah3 = ...
This way, the hidden stuff will be exported from Foo.Bar, but not included in the documentation. The documentation will only include one relatively unobtrusive link to the Foo.Bar.Hidden module as a whole.

erlang -import not working

I have an erlang program, compiled with rebar, after the new debian release, it won't compile anymore, complaining about this:
-import(erl_scan).
-import(erl_parse).
-import(io_lib).
saying:
bad import declaration
I don't know erlang, I am just trying to compile this thing.
Apparently something bad happened to -import recently http://erlang.org/pipermail/erlang-questions/2013-March/072932.html
Is there an easy way to fix this?
Well, -import(). is working but it does NOT do what you are expecting it to do. It does NOT "import" the module into your module, nor does it go out, find the module and get all the exported functions and allow you to use them without the module name. You use -import like this:
-import(lists, [map/2,foldl/3,foldr/3]).
Then you can call the explicitly imported functions without module name and the compiler syntactically transforms the call by adding the module name. So the compiler will transform:
map(MyFun, List) ===> lists:map(MyFun, List)
Note that this is ALL it does. There are no checks for whether the module exists or if the function is exported, it is a pure naive syntactic transformation. All it gives you is slightly shorter code. For this reason it is seldom used most people advise not to use it.
Note also that the unit of code for all operations is the module so the compiler does not do any inter-module checking or optimisation at all. Everything between modules like checking a modules existence or which functions it exports is done at run-time when you call a function in the other module.
No, there is no easy way to fix this. The source code has to be updated, and every reference to imported functions prefixed with the module in question. For example, every call to format should be replaced with io_lib:format, though you'd have to know which function was imported from which module.
You could start by removing the -import directives. The compilation should then fail, complaining about undefined functions. That is where you need to provide the correct module name. Look at the documentation pages for io_lib, erl_scan and erl_parse to see which functions are in which module.
Your problem is that you were using the experimental -import(Mod) directive which is part of parameterized modules. These are gone in R16B and onwards.
I often advise against using import. It hurts quick searches and unique naming of foreign calls. Get an editor which can quickly expand names.
Start by looking at what is stored in the location $ERL_LIBS, typically this points to /usr/lib/erlang/lib.

Resources