MicroHs icon indicating copy to clipboard operation
MicroHs copied to clipboard

Feature request: prefer module in the search path over a module in the package database

Open Yuras opened this issue 8 months ago • 3 comments

If I have a module that happen to have the same name as some other module in an unrelated package already installed by mcabal, then MicroHs silently uses the installed one. I think it should prefer the local one instead.

My use case is the following. I like to support older versions of libraries, and at the same time I don't like to clatter the code with CPP. So instead I create "shim" modules that export the current version of the API even for older libraries.

For example, in scanner I have a compat folder where I have e.g. Data.Either module. For versions of base older then 4.7.0 it exports isRight and isLeft, which where added later. For newer versions of base it just reexports the original module.

The benefits of such an approach are two fold. First of all, you always write code assuming the most recent version of API without any inline CPP. At the same time when developing the code locally you don't need the "shim" modules assuming that you are using the newest libraries, e.g. you can load the code into ghci without shims. Another benefit is that when you decide to stop supporting the old version of a library, you can just delete the "shim" module without changing the existing code at all.

Unfortunately it doesn't work with MicroHs. As a result, I have to make the shim module explicit, for example see https://github.com/Yuras/scanner/pull/14#discussion_r2328790024 Is it possible to change the behavior? It will help writing portable code.

Yuras avatar Sep 07 '25 18:09 Yuras

Here are exact steps to reproduce the issue:

tmp$ cat Main.hs 
module Main where

import Data.Char

main :: IO ()
main = print (unsafeChr 5)
tmp$ cat Data/Char.hs 
module Data.Char where

unsafeChr :: Int -> Char
unsafeChr _ = 'a'
tmp$ runhaskell Main.hs 
'a'
tmp$ mhs -r Main.hs

mhs: uncaught exception: error: "Main.hs": line 6, col 15: undefined value: unsafeChr
tmp$

Yuras avatar Sep 07 '25 18:09 Yuras

The fix for this would not be nice. Loading a package means that you populate the mhs compilation cache. Whenever you import a module you look in the cache to see if it's already there, if it is that's the one you get. To get the behaviour you want, each import would first have to check if there's a file in the search path that overrides the cached module. This is both slow and somewhat cumbersome. It also sounds like you'd like for the original and your override module to co-exist in the same program. This is impossible and against the MicroHs philosophy. There is at most one module for each module name. Unlike GHC, MicroHs does not include the package name in the name.

I will think about it, since I think you have a good use case.

augustss avatar Sep 07 '25 19:09 augustss

I have given it some thought. I'll probably change things to allow your use case, but not very seem.

augustss avatar Sep 08 '25 09:09 augustss