Title: HaRe: the Haskell Refactorer
1HaRe the Haskell Refactorer
- Huiqing Li
- Claus Reinke
- Simon Thompson
- University of Kent, Canterbury, UK
-
- www.cs.kent.ac.uk/projects/refactor-fp
2Overview
- Refactoring
- Haskell
- Refactoring Haskell
- Design adoption
- Demo
- Implementation
- Reflection
3Refactoring
- Refactoring means changing the design or
structure of a program without changing its
behaviour.
Refactor
Modify
4Splitting a function in two
5Splitting a function in two
6Splitting a function in two
7Splitting a function
- module Split where
- f String -gt String -gt String
- f ys foldr () y"\n" y lt- ys
8Splitting a function
- module Split where
- f String -gt String -gt String
- f ys foldr () y"\n" y lt- ys
9Splitting a function
- module Split where
- f String -gt String -gt String
- f ys join y "\n" y lt- ys
- where
- join foldr ()
10Splitting a function
- module Split where
- f String -gt String -gt String
- f ys join y "\n" y lt- ys
- where
- join foldr ()
11Splitting a function
- module Split where
- f String -gt String -gt String
- f ys join addNL
- where
- join foldr ()
- addNL y "\n" y lt- ys
12Splitting a function
- module Split where
- f String -gt String -gt String
- f ys join addNL
- where
- join foldr ()
- addNL y "\n" y lt- ys
13Splitting a function
- module Split where
- f String -gt String -gt String
- f ys join (addNL ys)
- where
- join foldr ()
- addNL ys y "\n" y lt- ys
14Splitting a function
- module Split where
- f String -gt String -gt String
- f ys join (addNL ys)
- where
- join foldr ()
- addNL ys y "\n" y lt- ys
15Splitting a function
- module Split where
- f String -gt String -gt String
- f ys join (addNL ys)
-
- join foldr ()
- addNL ys y "\n" y lt- ys
16Haskell 98
- Standard, lazy, strongly typed, functional
programming language. - Layout is significant offside rule and
idiosyncratic.
doSwap pnt applyTP (full_buTP (idTP adhocTP
inMatch
adhocTP inExp
adhocTP inDecl)) where inMatch
((HsMatch loc fun pats rhs ds)HsMatchP)
fun pnt case pats of
(p1p2ps) -gt do pats'lt-swap p1 p2 pats
return (HsMatch loc
fun pats' rhs ds) _ -gt
error "Insufficient arguments to swap."
inMatch m return m inExp exp_at_((Exp
(HsApp (Exp (HsApp e e1)) e2))HsExpP)
expToPNT e pnt swap e1 e2 exp
inExp e return e
17Why?
- The only design artefact is (in) the code.
-
- Semantics of functional languages support
large-scale transformations? - Building real tools to support functional
programming heavy lifting. - Platform for research and experimentation.
18Lift / demote
- f x y h
- where
- h
- ?
- Hide a function which is clearly subsidiary to f
clear up the namespace.
- f x y (h y)
-
- h y
- ?
- Makes h accessible to the other functions in the
module and beyond.
Free variables which parameters of f are used in
h? Need h not to be defined at the top level, ,
Type of h will generally change.
19Algebraic or abstract type?
data Tr a Leaf a Node a (Tr a) (Tr a)
flatten Tr a -gt a flatten (Leaf x)
x flatten (Node s t) flatten s flatten
t
Tr Leaf Node
20Algebraic or abstract type?
Tr isLeaf isNode leaf left right mkLeaf mkNode
data Tr a Leaf a Node a (Tr a) (Tr
a) isLeaf isNode
flatten Tr a -gt a flatten t isleaf t
leaf t isNode t flatten (left t)
flatten (right t)
21Design rationale
- Integrate with existing development tools.
- Work with the complete language Haskell 98
- Preserve comments and the formatting style.
- Reuse existing tools.
- Extensibility and scriptability.
22(No Transcript)
23(No Transcript)
24(No Transcript)
25The refactorings in HaRe
Move def between modules Delete/add to
exports Clean imports Make imports explicit data
type to ADT Short-cut, warm fusion All module
aware
- Rename
- Delete
- Lift / Demote
- Introduce definition
- Remove definition
- Unfold
- Generalise
- Add/remove parameters
26Information required
- Lexical structure of programs,
- abstract syntax,
- binding structure,
- type system and
- module system.
27The Implementation of HaRe
Information gathering
Pre-condition checking
Strafunski
Program transformation
Program rendering
28Finding free variables by hand
- instance FreeVbls HsExp where
- freeVbls (HsVar v) v
- freeVbls (HsApp f e)
- freeVbls f freeVbls e
- freeVbls (HsLambda ps e)
- freeVbls e \\ concatMap paramNames ps
- freeVbls (HsCase exp cases)
- freeVbls exp concatMap freeVbls cases
- freeVbls (HsTuple _ es)
- concatMap freeVbls es
- Boilerplate code 1000 noise 100 significant.
-
29Strafunski
- Strafunski allows a user to write general (read
generic), type safe, tree traversing programs,
with ad hoc behaviour at particular points. - Top-down / bottom up, type preserving / unifying,
full
stop
one
30Rename an identifier
- rename (Term t)gtPName-gtHsName-gtt-gtMaybe t
- rename oldName newName applyTP worker
- where
- worker full_tdTP (idTP adhocTP
idSite) -
- idSite PName -gt Maybe PName
- idSite v_at_(PN name orig)
- v oldName
- return (PN newName orig)
- idSite pn return pn
31Program rendering example
- -- This is an example
- module Main where
- sumSquares x y sq x sq y
- where sq Int-gtInt
- sq x x pow
- pow 2 Int
- main sumSquares 10 20
32Token stream and AST
- White space comments only in token stream.
- Modification of the AST guides the modification
of the token stream. - After a refactoring, the program source is
recovered from the token stream not the AST. - Heuristics associate comments with program
entities.
33Work in progress
- Fold against definitions find duplicate code.
- All, some or one? Effect on the interface
- f x e e
- Symbolic evaluation
- Data refactorings
- Interfaces
34API and DSL
Combining forms
???
Refactorings
Refactoring utilities
Library functions Grammar as data Strafunski
Strafunski
Haskell
35Conclusions
- Refactoring functional programming good fit.
- Real win from available libraries with work.
- Substantial effort in infrastructure.
- De facto vs de jure standards GHC vs H98.
- Correctness and verification
- Language independence