You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: kiselyov.md
+37-18Lines changed: 37 additions & 18 deletions
Original file line number
Diff line number
Diff line change
@@ -282,16 +282,44 @@ comS' :: CL
282
282
comS' =ComB:@ (ComB:@ComS) :@ComB
283
283
```
284
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*.
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.
286
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 ;-).
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:
288
296
289
297
```haskell
290
-
--| apply a CExpr of shape (CFun f) to argument x by evaluating (f x)
291
298
infixl0!
292
299
(!)::CExpr->CExpr->CExpr
293
300
(CFun f) ! x = f x
301
+
```
302
+
303
+
Thus:
304
+
```haskell
305
+
(Cfunid) !14=id14
306
+
id14=14
307
+
```
294
308
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`:
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
295
323
--| "link" a compiled expression into Haskell native functions.
296
324
-- application terms will be transformed into real (!) applications
297
325
-- combinator symbols will be replaced by their actual function definition
@@ -301,20 +329,10 @@ link definitions (CComb comb) = case lookup comb definitions of
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
332
```
317
333
334
+
In the same way I have re-implemented Ben's function `breakBulkLog` as `resolveBulkLog`.
335
+
318
336
319
337
## performance comparison
320
338
@@ -327,13 +345,14 @@ In my suite I am testing the performance of combinations of the following compon
327
345
328
346
- the compilers `compileBracket`, `compileEta` and `compileBulk` from the previous section
329
347
- 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`
331
350
332
351
So lets start with an overview of the results for the Graph Reduction Backend.
0 commit comments