Skip to content

Commit 4c5e743

Browse files
committed
on the way
1 parent 54fc083 commit 4c5e743

File tree

2 files changed

+37
-20
lines changed

2 files changed

+37
-20
lines changed

kiselyov.md

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -282,16 +282,44 @@ comS' :: CL
282282
comS' = Com B :@ (Com B :@ Com S) :@ Com B
283283
```
284284

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*.
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* without any prior code expansion.
286286

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 ;-).
287+
At the moment I have only implemented this idea 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+
In order to understand the solution we'll have a short recap of the HHI-Reducer core ideas [as described in my last post](https://thma.github.io/posts/2022-02-05-Evaluating-SKI-combinators-as-native-Haskell-functions.html):
290+
291+
The core idea is to take a combinator term and compile it into a set of Haskell functions. This is done in a function `link` as follows:
292+
293+
1. All combinators of the form `(CComb comb)` are mapped to haskell functions implementing the respective combinator reduction rule. For example the combinator `I` is mapped to `CFun id` and the combinator `K` is mapped to `CFun (CFun . const)`.
294+
295+
2. All applications `(CApp fun arg)` have to be replaced by actual function application. In our case we want apply functions of type `CExpr -> CExpr` that are wrapped by a `CFun` constructor. For this particular case we define an application operator `(!)` as follows:
288296

289297
```haskell
290-
-- | apply a CExpr of shape (CFun f) to argument x by evaluating (f x)
291298
infixl 0 !
292299
(!) :: CExpr -> CExpr -> CExpr
293300
(CFun f) ! x = f x
301+
```
302+
303+
Thus:
304+
```haskell
305+
(Cfun id) ! 14 = id 14
306+
id 14 = 14
307+
```
294308

309+
The mapping of Combinators to Haskell functions in step 1. is done by looking up a map of combinator definitions. This map contains definitions for all standard combinators and numeric operations. The Bulk combinators are not defined in this map. Instead they are resolved by the function `resolveBulk`:
310+
311+
```haskell
312+
resolveBulk :: Combinator -> CExpr
313+
resolveBulk (BulkCom "B" n) = iterate (comB' !) comB !! (n-1)
314+
resolveBulk (BulkCom "C" n) = iterate (comC' !) comC !! (n-1)
315+
resolveBulk (BulkCom "S" n) = iterate (comS' !) comS !! (n-1)
316+
```
317+
318+
It's interesting to note how this functions resembles the `breakBulkLinear` function. The only difference is that we are using the function application operator `(!)` instead of the data constructor `(:@)`.
319+
The function `link` is now defined as follows:
320+
321+
322+
```haskell
295323
-- | "link" a compiled expression into Haskell native functions.
296324
-- application terms will be transformed into real (!) applications
297325
-- combinator symbols will be replaced by their actual function definition
@@ -301,20 +329,10 @@ link definitions (CComb comb) = case lookup comb definitions of
301329
Nothing -> resolveBulk comb
302330
Just e -> e
303331
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)
316332
```
317333

334+
In the same way I have re-implemented Ben's function `breakBulkLog` as `resolveBulkLog`.
335+
318336

319337
## performance comparison
320338

@@ -327,13 +345,14 @@ In my suite I am testing the performance of combinations of the following compon
327345

328346
- the compilers `compileBracket`, `compileEta` and `compileBulk` from the previous section
329347
- the function factorial, fibonacci, ackermann and tak from the previous section
330-
- the execution backenda Graph Reduction Engine and the native Haskell functions implementaion from my previous post. I have not implemented the Bulk combinators in the graph reduction engine. So I am only testing this backend only with the `compileBracket` and `compileEta` compilers.
348+
- the execution backenda Graph Reduction Engine and the HHI-reducer implementaion from my previous post. I have not implemented the Bulk combinators in the graph reduction engine. So I am only testing this backend with the `compileBracket` and `compileEta` compilers.
349+
- the HHI-Reducer with both `resolveBulkLinear` and `resolveBulkLog`
331350

332351
So lets start with an overview of the results for the Graph Reduction Backend.
333352

353+
### Graph Reduction Engine
334354

335-
336-
##
355+
|
337356

338357

339358
![Alt text](image.png)

src/Kiselyov.hs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ comC' = Com B :@ (Com B :@ Com C) :@ Com B
225225
comS' :: CL
226226
comS' = Com B :@ (Com B :@ Com S) :@ Com B
227227

228-
229-
230228
breakBulkLog :: Combinator -> Int -> CL
231229
breakBulkLog c 1 = Com c
232230
breakBulkLog B n = foldr (:@) (Com B) $ map (bs!!) $ init $ bits n where

0 commit comments

Comments
 (0)