Wednesday, October 02, 2024

[mlzpqxqu] import with type signature

proposal for a Haskell language extension: when importing a function from another module, one may optionally also specify a type signature for the imported function.  this would be helpful for code understanding.  the reader would have immediately available the type of the imported symbol, not having to go track down the type in the source module (which may be many steps away when modules re-export symbols, and the source module might not even have a type annotation), nor use a tool such as ghci to query it.  (maybe the code currently fails to compile for other reasons, so ghci is not available.)

if a function with the specified type signature is not exported by an imported module, the compiler can offer suggestions of other functions exported by the module which do have, or unify with, the imported type signature.  maybe the function got renamed in a new version of the module.

or, the compiler can do what Hoogle does and search among all modules in its search path for functions with the given signature.  maybe the function got moved to a different module.

the specified type signature may be narrower than how the function was originally defined.  this can limit some of the insanity caused by the Foldable Traversable Proposal (FTP):

import Prelude(length :: [a] -> Int) -- prevent length from being called on tuples and Maybe

various potentially tricky issues:

  1. a situation similar to the diamond problem (multiple inheritance) in object-oriented programming: module A defines a polymorphic function f, imported then re-exported by modules B and C.  module D imports both B and C, unqualified.  B imports and re-exports f from A with a type signature more narrow than originally defined in A.  C does not change the type signature.  what is the type of f as seen by D?  which version of f, which path through B or C, does D see?  solution might be simple: if the function through different paths are not identical, then the user has to qualify.

  2. the following tries to make List.length available only for lists, and Foldable.length available for anything else.  is this asking for trouble?

    import Prelude hiding(length);
    import qualified Prelude(length :: [a] -> Int) as List;
    import qualified Prelude(length) as Foldable;

No comments :