Skip to content

Commit 54fc083

Browse files
committed
some progress
1 parent 1952cdb commit 54fc083

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

kiselyov.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ the previous example with two variables.
232232
Now the Kiselyov algorithms really start to shine. `compileEta` produces code is significantly smaller as the baseline. And `compileBulk` output is even smaller.
233233

234234

235+
235236
### The tak function
236237

237238
```haskell
@@ -255,13 +256,72 @@ main = tak 7 4 2
255256

256257
In this example with four variables the trend continues. `compileEta` produces code is significantly smaller as the baseline. And `compileBulk` output now is only about 1/3 of the baseline.
257258

259+
## Executing Bulk Combinators
260+
261+
We have seen that Kisekyov's algorithms produce code that makes use of *Bulk Combinators* like `S4`, `B3` or `C2`. Ben Lynn defines the semantics of these combinators as follows:
262+
263+
<img style="align:center;" src="https://latex.codecogs.com/svg.image?\begin{align*}B_{n&plus;1}&=B'B_n\\C_{n&plus;1}&=C'C_n\\S_{n&plus;1}&=S'S_n\end{align*}" />
264+
265+
where `B'`, `C'` and `S'` defined as follows:
266+
267+
<img style="align:center;" src="https://latex.codecogs.com/svg.image?\begin{align*}B'&=BB\\C'&=B(BC)B\\S'&=B(BS)B\end{align*}" />
268+
269+
Ben also defines the following function that converts a combinator term with *Bulk Combinators* to a combinator term with only standard combinators:
270+
271+
```haskell
272+
breakBulkLinear :: Combinator -> Int -> CL
273+
breakBulkLinear B n = iterate (comB' :@) (Com B) !! (n - 1)
274+
breakBulkLinear C n = iterate (comC' :@) (Com C) !! (n - 1)
275+
breakBulkLinear S n = iterate (comS' :@) (Com S) !! (n - 1)
276+
277+
comB' :: CL
278+
comB' = Com B:@ Com B
279+
comC' :: CL
280+
comC' = Com B :@ (Com B :@ Com C) :@ Com B
281+
comS' :: CL
282+
comS' = Com B :@ (Com B :@ Com S) :@ Com B
283+
```
284+
285+
As we have seen in the output of the `compileBulkLinear` this conversion expands the code size. To avoid this expansion of the combinator code I have implemented a solution to directly execute *Bulk Combinators*.
286+
287+
At the moment I have only implemented it in the [Haskell-In-Haskell](https://wiki.haskell.org/wikiupload/0/0a/TMR-Issue10.pdf) inspired HHI-Reducer. Implementing it for the Graph Reduction Engine is left as an exercise for the reader ;-).
288+
289+
```haskell
290+
-- | apply a CExpr of shape (CFun f) to argument x by evaluating (f x)
291+
infixl 0 !
292+
(!) :: CExpr -> CExpr -> CExpr
293+
(CFun f) ! x = f x
294+
295+
-- | "link" a compiled expression into Haskell native functions.
296+
-- application terms will be transformed into real (!) applications
297+
-- combinator symbols will be replaced by their actual function definition
298+
link :: CombinatorDefinitions -> CExpr -> CExpr
299+
link definitions (CApp fun arg) = link definitions fun ! link definitions arg
300+
link definitions (CComb comb) = case lookup comb definitions of
301+
Nothing -> resolveBulk comb
302+
Just e -> e
303+
link _definitions expr = expr
304+
305+
306+
resolveBulk :: Combinator -> CExpr
307+
resolveBulk (BulkCom "B" n) = iterate (comB' !) comB !! (n-1)
308+
resolveBulk (BulkCom "C" n) = iterate (comC' !) comC !! (n-1)
309+
resolveBulk (BulkCom "S" n) = iterate (comS' !) comS !! (n-1)
310+
311+
comS :: CExpr
312+
comS = CFun (\f -> CFun $ \g -> CFun $ \x -> f!x!(g!x)) -- S F G X = F X (G X)
313+
314+
comS' :: CExpr
315+
comS' = CFun (\p -> CFun $ \q -> CFun $ \r -> CFun $ \s -> p!(q!s)!(r!s)) -- S' P Q R S = P (Q S) (R S)
316+
```
317+
258318

259319
## performance comparison
260320

261321
So far we have seen that for functions with more than two variables the Kiselyov algorithms generate code that is significantly smaller than optimized versions of classic bracket abstraction.
262322
But what about performance? Is the code generated by the Kiselyov algorithms also faster?
263323

264-
To answer this question i have implemented a simple benchmarking suite based on the [micro-benchmarking framework Criterion](http://www.serpentine.com/criterion/).
324+
To answer this question I have set up a benchmarking suite based on the [micro-benchmarking framework Criterion](http://www.serpentine.com/criterion/).
265325

266326
In my suite I am testing the performance of combinations of the following components:
267327

0 commit comments

Comments
 (0)