Refactoring Haskell 98 Programs Vs. Refactoring Erlang Programs - PowerPoint PPT Presentation

About This Presentation
Title:

Refactoring Haskell 98 Programs Vs. Refactoring Erlang Programs

Description:

fac :: Int - Int. fac 0 = 1. fac n | n 0 = n * fac(n-1) 11/7/09. FP ... fac m = tfac m b -- renaming m to b or b to m causes name capture. where. tfac o k = k ... – PowerPoint PPT presentation

Number of Views:90
Avg rating:3.0/5.0
Slides: 27
Provided by: hl1
Category:

less

Transcript and Presenter's Notes

Title: Refactoring Haskell 98 Programs Vs. Refactoring Erlang Programs


1
Refactoring Haskell 98 Programs
Vs.Refactoring Erlang Programs
  • Huiqing Li
  • Simon Thompson

2
Outline
  • Haskell 98 Vs. Erlang
  • Behaviour and Layout preservation
  • Renaming a variable/function name
  • Generalise a definition
  • Implementation
  • Conclusion

3
Haskell 98 Vs. Erlang
  • Haskell 98 a lazy, statically typed, purely
    functional programming language featuring,
    higher-order functions, polymorphism, type
    classes and monadic effects.
  • Erlang a strict, dynamically typed functional
    programming language with support for
    concurrency, communication, distribution and
    fault-tolerance.

4
Haskell 98 Vs. Erlang
  • Similarities
  • -- Erlang
  • Functional
  • Higher-order
  • Pattern matching
  • Module system
  • General purpose language but better suited for
    concurrent applications.

-- Haskell Functional Higher-order Pattern
matching Module system General purpose
5
Haskell 98 Vs. Erlang
-- Factorial In Haskell. module Fact where fac
Int -gt Int fac 0 1 fac n ngt0 n fac(n-1)
Factorial In Erlang. -module (fact). -export
(fac/1). fac(0) -gt 1 fac(N) when N gt 0 -gt N
fac(N-1).
6
Haskell 98 Vs. Erlang
  • Differences
  • -- Erlang
  • Strict
  • Dynamically Typed
  • Non-pure
  • No explicit type signatures
  • All named functions are top-level
  • No partial application
  • Layout insensitive
  • Simpler comment rules
  • Simpler module interface

-- Haskell Lazy Statically typed Pure Allows
explicit type signatures Nested function
declarations Allows Partial application Layout
sensitive Complex comment rules Complex module
interface
7
Haskell 98 Vs. Erlang
  • Differences
  • -- Erlang
  • Concurrency
  • Communication
  • Fault-tolerance
  • Distribution
  • OTP Design principles
  • Macro directives
  • . . .

-- Haskell Function composition Type
declarations Type classes Monads ...
8
Haskell Vs. Erlang -- refactoring
opportunities
Haskell Refactorings
Erlang Refactorings
9
Haskell Vs. Erlang -- refactoring
opportunities
  • Common refactorings renaming, generalising a
    function definition, removing unused
    functions/parameters, moving a definition from
    one module to another, swapping the order of
    arguments , etc.
  • Haskell-specific refactorings data-type
    declaration or type class related refactorings,
    etc.
  • Erlang-specific refactorings concurrency-related
    refactorings, OTP-related refactoring, etc.

10
Behaviour preservation
  • Haskell
  • The behaviour of the main function should not be
    changed.
  • Erlang
  • The behaviour of those exported functions
    should not be changed.

11
Program Layout preservation
  • Haskell people tend stick to their own layout,
    therefore standard pretty-printer does not help
    too much.
  • Erlang people tend to accept the standard layout,
    partially because most Erlang people use Emacs as
    the editor, therefore standard pretty-printed is
    acceptable.

12
Renaming a variable name
  • Renames all and only those uses of the variable,
    and not every use of the particular variable
    name.
  • This refactoring should not cause name conflict,
    or name capture.
  • This refactoring needs a clear picture of the
    binding structure (for variables) of the program
    under refactorings.

module Fact where fac m tfac m b
-- renaming m to b or b to m causes name
capture where tfac o k k tfac n k
n gt0 tfac (n-1) (nk) -- renaming n to k
causes name conflict b 1
13
Renaming a variable name
  • In Haskell
  • A pattern does not contain applied occurrences of
    variables
  • A variable is only associated with one binding
    occurrence.
  • All patterns must be linear (no variable may
    appear more than once)
  • In Erlang
  • Binding occurrence of a variable will always be
    in a pattern, but a pattern may also contain
    applied occurrences of variables.
  • A variable may have more than one binding
    occurrences.
  • Non-linear patterns are allowed.

bar(S) -gt case S of 1 -gt S1 3, S1 _ -gt
S1 4, S1 end, S1 S1.
14
Renaming a function name
  • Renames all and only those uses of the function,
    and not every use of the particular function
    name.
  • This refactoring should not cause name conflict,
    name shadowing or name capture.
  • This refactoring needs a clear picture of the
    binding structure (for functions) of the program
    under refactorings.

15
Renaming a function name
  • In Haskell
  • The nested function declarations
  • A module can export not only the functions
    defined in this module, but also those functions
    imported by this module.
  • Function name ( module name) identifies a
    function.
  • Function application function name followed by
    arguments.
  • In Erlang
  • All named functions are top-level.
  • A module can only export those functions that are
    defined in this module (i.e. no transitive
    exporting).
  • Function name arity ( module name) identifies
    a function.
  • Function application is much more complex.


16
Renaming a function name
  • Function applications expressions in Erlang
  • Fun (E1, , En) where Fun is a function
    name.
  • eg.
    length(1,2,3).
  • E0(E1, ., En)
  • case1 the value of E0 is a tuple. E.g. lists,
    reverse(1,2,3)
  • case2 the value of E0 is an implicit fun
    expression.
  • eg. (fun (X) -gt X 1 end) (2)
  • case3 the value of E0 is an explicit fun
    expression.
  • eg. (fun listsreverse/1) (1,2,3)
  • EmE0(E1, , En) eg
    listsreverse(1,2,3).
  • Meta function application in Erlang
  • erlangapply ( Module, Fun, Args)
  • eg. erlangapply (lists, reverse, a,b,c)

17
Renaming a function name
  • The flexibility of function application
    expressions and meta function application in
    Erlang make it hard or impossible to build a
    complete call graph, or to clarify the binding
    structure of the program under refactoring.
  • Example

-module (math). -export(f/1, f/2,f2/1). f
(X) -gt X. f (X, Y ) -gt X Y. f2(Args) -gt
erlangapply( math, f, Args).
18
Generalise a function definition
  • Generalise a definition by selecting a
    sub-expression of the right-hand side and making
    this the value of a new argument added to the
    definition of the function or constant.

-module (test). -export(f/1). add_one
(N, HT) -gt HN add_one(N,T) add_one
(N,) -gt . f(X) -gt add_one(1, X).
19
Generalise a function definition
  • Erlang is a strict language, i.e. arguments are
    evaluated before function application.
  • Erlang is not purely functional, mutable stuff
    (message sends/receives and state dependent
    responses) play an important part in most large
    programs.
  • Strict non pure cause problems when generalise
    a function on a subexpression that has
    side-effects.

20
Generalise a function definition
  • Example

-module (test). -export(f/0). repeat(0) -gt
ok repeat(N) -gt ioformat (hello\n"),
repeat(N-1). f( ) -gt repeat(5).
-module (test). -export(f/0). repeat(A, 0) -gt
ok repeat(A, N) -gt A,
repeat(A,N-1). f( ) -gt repeat (ioformat
(hello\n), 5).
Function f/0 behaves differently before and after
transformation.
21
Generalise a function definition
  • Our solution using higher order functions.

-module (test). -export(f/0). repeat(0) -gt
ok repeat(N) -gt ioformat (hello\n"),
repeat(N-1). f( ) -gt repeat(5).
-module (test). -export(f/0). repeat(A, 0) -gt
ok repeat(A, N) -gt A( ),
repeat(A,N-1). f( ) -gt repeat (fun(
)-gtioformat (hello\n) end, 5).
Function f/0 behaves the same before and after
transformation.
22
Generalise a function definition
  • By using higher-order functions and the
    flexibility of function application provide by
    Erlang, we could also generalise a function on a
    sub-expression which contains locally declared
    variables.
  • Example

-module (test). -export(b/1). broadcast (Msg,
Pid Pids) -gt Pid ! Msg, broadcast
(Msg, Pids) broadcast(_, ) -gt true. b (Ps )
-gt broadcast (The message, Ps).
23
Generalise a function definition
-module (test). -export(b/1). broadcast (Msg,
Pid Pids) -gt Pid ! Msg, broadcast
(Msg, Pids) broadcast(_, ) -gt true. b (Ps )
-gt broadcast (The message, Ps).
-module (test). -export(b/1). broadcast (F,
Msg, Pid Pids) -gt F (Pid, Msg),
broadcast (F, Msg, Pids) broadcast(F, _, ) -gt
true. b (Ps ) -gt broadcast ( fun(Pid, Msg) -gt
Pid ! Msg end, The message, Ps).
24
Implementation
  • The Haskell Refactorer, HaRe is implemented in
    Haskell,
  • The Erlang Refactorer is implemented in Erlang.
  • In the implementation of HaRe, lots of effort
    has been put to comment and layout preserving,
    whereas this is not the case in the
    implementation of the Erlang refactorer.
  • Type errors can be more easily detected during
    the implementation of HaRe.

25
Implementation
  • The implementation of the Erlang Refactorer.

Program source
Scanner Parser Syntax Tools
AST with comments
Program analysis and transformation
Transformed AST
Pretty printer
Program source
26
Conclusion
  • Different language features expose different
    refactoring opportunities.
  • Refactoring Erlang programs involve more
    condition analyses.
  • OTP may impose some constraints on refactoring
    particular programs.
  • Experience from refactoring Haskell program
    helps to some extent.
  • Proof of behaviour preservation may be more
    difficult for Erlang programs.
Write a Comment
User Comments (0)
About PowerShow.com