Open In App

What is Defunctionalization

Defunctionalization is a compile-time conversion which removes higher-order functions by replacing the higher-order functions with a single first-order apply function. 

This method was first represented by John C. Reynolds in the year 1972. It was represented in John C. Reynolds’s paper named “Definitional Interpreters for Higher-Order Programming Languages”. His examination was that :  



One difficulty with the idea of defunctionalization is that :

In a program, executes on all function abstractions rather than having a single applied function. To determine what functions should be called at each function application site, there are different kinds of control flow analysis (including simple difference based on type signature) and there is also a specialized apply function which may be recommended alternatively. Instead, indirect calls through function pointers are supported by the target language, which may be well organized and extensible than a dispatch-based approach. 



Steps for Defunctionalization :
There are two steps to defunctionalize a higher-order function (HOF) :

  1. For each and every position where the higher-order function (HOF) is used and applied to a function, restore that function with the value of the assigned data type to constitute that function. This is known as a “defunctionalization symbol”.
  2. According to HOF’s definition, if a function parameter is applied anywhere, restore that applied function parameter with a call to a dedicated first-order function that will explain the defunctionalization symbol for which this parameter now stands for. Often, this function is called apply and sometimes it is known as eval.

Functional programming ideas are made with the help of Defunctionalization. There is a lot of value of Defunctionalization in languages which have already higher-order functions, i.e, functional languages.

Despite removing higher order functionalities, defunctionalization is  a way of mechanically transforming interpreters into abstract machines and it also represents functions by function objects from object-oriented programming languages.

Below is the example given by Olivier Danvy, which is translated to Haskell :
Below is the tree datatype :

data Tree a = Leaf a
            | Node (Tree a) (Tree a)

Now, here we will have to defunctionalize the program given below :

cons :: a -> [a] -> [a]
cons x xs = x : xs

o :: (b -> c) -> (a -> b) -> a -> c
o f g x = f (g x)

flatten :: Tree t -> [t]
flatten t = walk t []

walk :: Tree t -> [t] -> [t]
walk (Leaf x)     = cons x
walk (Node t1 t2) = o (walk t1) (walk t2)

Now, to defunctionalize the above program, we will replace all higher-order functions (i.e, o which is the only higher order function here) with lam datatype value and rather than calling them directly, we will initiate an apply function that simplify the datatype –

data Lam a = LamCons a
           | LamO (Lam a) (Lam a)

apply :: Lam a -> [a] -> [a]
apply (LamCons x)  xs = x : xs
apply (LamO f1 f2) xs = apply f1 (apply f2 xs)

cons_def :: a -> Lam a
cons_def x  = LamCons x

o_def :: Lam a -> Lam a -> Lam a
o_def f1 f2 = LamO f1 f2

flatten_def :: Tree t -> [t]
flatten_def t = apply (walk_def t) []

walk_def :: Tree t -> Lam t
walk_def (Leaf x)     = cons_def x
walk_def (Node t1 t2) = o_def (walk_def t1) (walk_def t2)
Article Tags :