Title: Refactoring Haskell Programs
1Refactoring Haskell Programs
- Huiqing Li
- Computing Lab, University of Kent
- www.cs.kent.ac.uk/projects/refactor-fp/
2Outline
- Refactoring
- HaRe The Haskell Refactorer
- Implementation of HaRe
- Formalisation of Haskell Refactorings
- Future Work
3Refactoring
- What? Changing the structure of existing code
without changing its behaviour.
module Main (main) where f z y y f z (y
z) main y print f 1 10
?
4HaRe The Haskell Refactorer
- A tool for refactoring Haskell 98 programs.
- Full Haskell 98 coverage.
- Driving concerns usability and extensibility.
- Integrated with the two program editors (X)Emacs
and Vim. - Preserves both comments and layout style of the
source.
5HaRe The Haskell Refactorer
- Implemented in Haskell, using Programaticas
frontends and Strafunskis generic traversals. - Programatica a system implemented in Haskell for
the development of high-assurance software in
Haskell. - Strafunski A Haskell library for supporting
generic programming in application areas that
involve term traversals over large abstract
syntaxes.
6Refactorings Implemented in HaRe
- Structural Refactorings
- Module Refactorings
- Data-Oriented Refactorings
7Refactorings Implemented in HaRe
- Structural Refactorings
- Generalise a definition
module Main (main) where f y y
f (y 1) main print f 10
module Main (main) where f z y y f z (y
z) main y print f 1 10
?
8Refactorings Implemented in HaRe
- Structural Refactorings (cont.)
- Rename an identifier
- Promote/demote a definition to widen/narrow its
scope - Delete an unused function
- Duplicate a definition
- Unfold a definition
- Introduce a definition to name an identified
expression - Add an argument to a function
- Remove an unused argument from a function
-
9Refactorings Implemented in HaRe
- Move a definition from one module to another
module
module Test ( ) where
module
Main where import Test f y y f (y 1)
main print f 10
module Test (f) where f y y f (y
1)
module Main where import Test
main print f 10
?
10Refactorings Implemented in HaRe
- Module Refactorings (cont.)
- Clean the imports
- Make the used entities explicitly imported
- Add an item to the export list
- Remove an item from the export list
11Refactorings Implemented in HaRe
- Data-oriented Refactorings
- From concrete to abstract data-type (ADT), which
is a composite refactoring built from a sequence
of primitive refactorings.
12Refactorings Implemented in HaRe
13Refactorings Implemented in HaRe
14Implementation of HaRe
analysis and transformation using
Strafunski (with DrIFT)
Programatica (lexer, parser, type
checker, module analysis)
extract program from token stream
Program
TS
Program
AST
TS token stream AST annotated abstract syntax
tree MI module information
15The Architecture of HaRe
Composite Refactorings
Elementary Refactorings
RefacUtils (HaRe_API)
RefacLocUtils
Programatica
Strafunski (with DrIFT)
16Formalisation of Refactorings
- Advantages
- Clarify the definition of refactorings in terms
of side-conditions and transformations. - Improve our confidence in the behaviour-preservati
on of refactorings. - Guide the implementation of refactorings.
- Challenges
- Haskell is a non-trivial language.
- Haskell does not have an officially defined
semantics.
17Formalisation of Refactorings
- Our Strategy
- Start from a simple language (?letrec).
- Extend the language gradually to formalise more
complex refactorings.
18Formalisation of Refactorings
- The specification of a refactoring contains four
parts - The representation of the program before the
refactorings, say P1 - The side-conditions for the refactoring.
- The representation of the program after the
refactorings, say P2. - A proof showing that P1 and P2 have the same
functionality under the side-conditions.
19Formalisation of Refactorings
- The ?-calculus with letrec (?letrec)
- Syntax of ?letrec terms.
E x ?x.E E1 E2
letrec D in E D ? xiEi D, D
- Use the call-by-name semantics developed by Zena
M. Ariola and Stefan Blom in the paper Lambda
Calculi plus letrec.
20Formalisation of Generalisation
module Main (main) where f y y
f (y 1) main print f 10
module Main (main) where f z y y f z (y
z) main print f 1 10
?
21Formalisation of Generalisation
- Formal definition of Generalisation using ?letrec
-
Given the expression Assume E is a
sub-expression of Ei, and Ei CE.
letrec x1E1, ..., xi Ei
, ..., xn En in E0
22Formalisation of Generalisation
- Formal definition of Generalisation using ?letrec
- The condition for generalising the definition
xiEi on E is - xi?FV(E ) Æ 8x, e (x 2FV(E ) Æ e 2 sub(Ei, C)
) x 2FV(e))
module Main (main) where f y y
f (y 1) main print f 10
23Formalisation of Generalisation
- Formal definition of Generalisation using ?letrec
- The condition for generalising the definition
xiEi on E is - xi?FV(E ) Æ 8x, e (x 2FV(E ) Æ e 2 sub(Ei,C)
) x 2FV(e))
module Main (main) where f y y
f (y 1) main print f 10
?
24Formalisation of Generalisation
- Formal definition of Generalisation using ?letrec
- The condition for generalising the definition
xiEi on E is - xi?FV(E ) Æ 8x, e (x 2FV(E ) Æ e 2 sub(Ei,C)
) x 2FV(e))
module Main (main) where f y y
f (y 1) main print f 10
?
25Formalisation of Generalisation
- Formal definition of Generalisation using ?letrec
- After generalisation, the original expression
becomes
module Main (main) where f y y
f (y 1) main print f 10
letrec x1 E1 xi xiE,
..., xi ? z.Czxixi z,
..., xn
En xi xi E in E0 xi xi E, where
z is a fresh variable.
?
module Main (main) where f z y y f z (y
z) main print f 1 10
26Formalisation of Generalisation
- Formal definition of Generalisation using ?letrec
- Proof. Decompose the transformation into a number
of sub steps, if each sub step is
behaviour-preserving, then the transformation is
behaviour-preserving.
27Formalisation of Generalisation
Step1 add definition x ? z.Cz , where x
and z are fresh variables, and CEEi.
letrec x1E1, ..., xi
Ei, x ? z.Cz, ...,
xn En in E0
module Main (main) where f y y f (y 1) x
z y y f ( y z) main print f 10
Step 2 Replace Ei with x E. (Note Ei x
E)
28Formalisation of Generalisation
Step 2 Replace Ei with x E. (Note Ei x
E)
letrec x1E1, ..., xi x
E, x ? z.Cz, ...,
xn En in E0
module Main (main) where f y x 1 y x z y y
f ( y z) main print f 10
Step 3 Unfolding xi in the right-hand side of x.
29Formalisation of Generalisation
Step 3 Unfolding xi in the right-hand side of x.
letrec x1E1, ..., xi x
E, x ? z.Cz x_i x E,
..., xn En in E0
module Main (main) where f y x 1 y x z y y
x 1 ( y z) main print f 10
Step 4 In the definition of x, replace E with
z, and prove this does not change the semantics
of x E.
30Formalisation of Generalisation
Step 4 In the definition of x, replace E with
z. and prove this does not change the semantics
of x E.
letrec x1E1, ..., xi x
E, x ? z.Cz x_i x z,
..., xn En in E0
module Main (main) where f y x 1 y x z y y
x z ( y z) main print f 10
Step 5 Unfolding the occurrences of xi.
31Formalisation of Generalisation
Step 5 Unfolding the occurrences of xi.
letrec x1E1 xi x E , ...,
xi x E, x ? z.Cz xi x
z, ..., xn En xi x
E in E0 xi x E
module Main (main) where f y x 1 y x z y y
x z ( y z) main print x 1 10
Step 6 Remove the definition of xi.
32Formalisation of Generalisation
Step 6 Remove the definition of xi.
letrec x1E1 xi x E , ...,
x ? z.Cz xi x z, ...,
xn En xi x E in E0 xi x E
module Main (main) where x z y y x z ( y
z) main print x 1 10
Step 7 Rename x to xi and simplify the
substitution.
33Formalisation of Generalisation
letrec x1E1 xi x E xxi ,
..., x ? z.Cz xi x z xxi,
..., xn En xi x E
xxi in E0 xi x E xxi
?
letrec x1 E1 xi xiE,
..., xi ? z.Czxixi z,
..., xn
En xi xi E in E0 xi xi E
module Main (main) where f z y y f z ( y
z) main print f 1 10
34Formalisation of Refactorings
- ?letrec has been extended to model the Haskell
module system (?M). - The move a definition from one module to another
refactoring has also been formalised - using ?M.
35Future Work
- Adding more refactoring to HaRe.
- Making use of type information.
- Coping with modules without source code.
- More interaction between HaRe and the user.
- Further development of the formalisation of
refactorings. - Metric-based refactoring.
- Support for scripting refactorings.
- Porting HaRe to GHC
- . . .
36Questions?
www.cs.kent.ac.uk/projects/refactor-fp/