


@ 5,12 +5,6 @@ tags: ["Haskell"] 




draft: true 




 









<style> 




img, figure.small img { maxheight: 20rem; } 




figure.tiny img { maxheight: 15rem; } 




figure.medium img { maxheight: 30rem; } 




</style> 









I recently got to use a very curious Haskell technique 




{{< sidenote "right" "productionnote" "in production:" >}} 




As production as research code gets, anyway! 



@ 132,7 +126,7 @@ length ((:) 1 []) 




We're now ready to draw the graph; in this case, it's pretty much identical 




to the syntax tree of the last form of our expression: 









{{< figure src="length_1.png" caption="The initial graph of `length [1]`." >}} 




{{< figure src="length_1.png" caption="The initial graph of `length [1]`." class="small" >}} 









In this image, the `@` nodes represent function application. The 




root node is an application of the function `length` to the graph that 



@ 143,7 +137,7 @@ list, and function applications in Haskell are 




in the process of evaluation, the body of `length` will be reached, 




and leave us with the following graph: 









{{< figure src="length_2.png" caption="The graph of `length [1]` after the body of `length` is expanded." >}} 




{{< figure src="length_2.png" caption="The graph of `length [1]` after the body of `length` is expanded." class="small" >}} 









Conceptually, we only took one reduction step, and thus, we haven't yet gotten 




to evaluating the recursive call to `length`. Since `(+)` 



@ 175,7 +169,7 @@ let x = square 5 in x + x 









Here, the initial graph looks as follows: 









{{< figure src="square_1.png" caption="The initial graph of `let x = square 5 in x + x`." >}} 




{{< figure src="square_1.png" caption="The initial graph of `let x = square 5 in x + x`." class="small" >}} 









As you can see, this _is_ a graph, but not a tree! Since both 




variables `x` refer to the same expression, `square 5`, they 



@ 183,7 +177,7 @@ are represented by the same subgraph. Then, when we evaluate `square 5` 




for the first time, and replace its root node with an indirection, 




we end up with the following: 









{{< figure src="square_2.png" caption="The graph of `let x = square 5 in x + x` after `square 5` is reduced." >}} 




{{< figure src="square_2.png" caption="The graph of `let x = square 5 in x + x` after `square 5` is reduced." class="small" >}} 









There are two `25`s in the graph, and no more `square`s! We only 




had to evaluate `square 5` exactly once, even though `(+)` 



@ 215,7 +209,7 @@ pick `f = (1:)`. That is, `f` is a function that takes a list, 




and prepends `1` to it. Then, after constructing the graph of `f x`, 




we end up with the following: 









{{< figure src="fixpoint_2.png" caption="The graph of `fix (1:)` after it's been reduced." >}} 




{{< figure src="fixpoint_2.png" caption="The graph of `fix (1:)` after it's been reduced." class="small" >}} 









We see the body of `f`, which is the application of `(:)` first to the 




constant `1`, and then to `f`'s argument (`x`, in this case). As 



@ 254,11 +248,11 @@ of using application nodes `@`, let's draw an application of a 




function `f` to arguments `x1` through `xn` as a subgraph with root `f` 




and children `x`s. The below figure demonstrates what I mean: 









{{< figure src="notation.png" caption="The new visual notation used in this section." >}} 




{{< figure src="notation.png" caption="The new visual notation used in this section." class="small" >}} 









Now, let's write the initial graph for `doRepMax [1,2]`: 









{{< figure src="repmax_1.png" caption="The initial graph of `doRepMax [1,2]`." >}} 




{{< figure src="repmax_1.png" caption="The initial graph of `doRepMax [1,2]`." class="small" >}} 









Other than our new notation, there's nothing too surprising here. 




The first step of our hypothetical reduction would replace the application of `doRepMax` with its 



@ 268,7 +262,7 @@ the tuple, we apply `repMax` to the list `[1,2]` and the first element 




of its result. The list `[1,2]` itself 




consists of two uses of the `(:)` function. 









{{< figure src="repmax_2.png" caption="The first step of reducing `doRepMax [1,2]`." >}} 




{{< figure src="repmax_2.png" caption="The first step of reducing `doRepMax [1,2]`." class="small" >}} 









Next, we would also expand the body of `repMax`. In 




the following diagram, to avoid drawing a noisy amount of 



@ 372,7 +366,7 @@ further, so that's what the mysterious force receives. Just like that, 




there's nothing left to print to the console. The mysterious force ceases. 




After removing the unused nodes, we are left with the following graph: 









{{< figure src="repmax_10.png" caption="The result of reducing `doRepMax [1,2]`." >}} 




{{< figure src="repmax_10.png" caption="The result of reducing `doRepMax [1,2]`." class="small" >}} 









As we would have expected, two `2`s were printed to the console, and our 




final graph represents the list `[2,2]`. 



