Widen or narrow definition scope


Identity: Promote
Category: MultiModule Naming
Classifiers: promote definition
Internal cross references:
External cross references: XXX
Language: Haskell

Description:

A definition is lifted from a where or let into the surrounding binding group. Such lifting widens the scope of the definition.


showAll :: Show a => [a] -> String
showAll = table . map show
    where
    format []     = []
    format [x]    = [x]
    format (x:xs) = (x ++ "\n") : format xs

    table = concat . format
  

showAll :: Show a => [a] -> String
showAll = table . map show
    where
    table = concat . format
    
format []     = []
format [x]    = [x]
format (x:xs) = (x ++ "\n") : format xs
  

General comment:

Left to right comment:

This refactoring is only possible if all the bindings to the free names in the definition are accessible in the scope to which the definition is moved. For a more liberal refactoring see Promotion with compensation.

In the version presented here, if the whole module that contains the lifted definition is implicitly exported, lifting a definition to the top-level will make it also be implicitly exported. If this causes any ambiguity/conflicting exports problems in a client module, the lifted definition name will be added to the hiding list of the corresponding import declaration in this client module.

Right to left comment:

In the version presented here, the definition can only be moved if it is used in a single local scope. It would also be possible to move the definition it into all scopes that use it; this would result in the definition being duplicated.

Left to right conditions:

The refactoring should not affect the binding structure of the program.

  • Widening the scope of the binding must not capture independent uses of the name in the outer scope.
  • There should be no existing definition of the name in the outer binding group (irrespective of whether or not it is used).
  • The binding to be promoted must not make use of bindings in the inner scope.

Right to left conditions:

The refactoring should not affect the binding structure of the program.

  • All uses of the binding to be moved must be within the inner scope to which the definition is being moved.
  • Free variables in the binding must not be captured when it is moved over nested scopes.
  • Moreover, there should be no definition of the name in the inner binding group (irrespective of whether or not it is used).

A top-level definition which is explicitly exported by the containing module can not be demoted, no matter whether it used by other modules or not. 

Analysis required:

Static scope analysis; call graph; module analysis.