Tree

Let's start the final chapter of Learn You a Haskell for Great Good: Zippers:

In this chapter, we'll see how we can take some data structure and focus on a part of it in a way that makes changing its elements easy and walking around it efficient.

I can see how this could be useful in Scala since equality of case classes are based on its content and not the heap location. This means that even if you just want to identify different nodes under a tree structure if they happen to have the same type and content Scala would treat the same.

TreeLoc

LYAHFGG:

With a pair of Tree a and Breadcrumbs a, we have all the information to rebuild the whole tree and we also have a focus on a sub-tree. This scheme also enables us to easily move up, left and right. Such a pair that contains a focused part of a data structure and its surroundings is called a zipper, because moving our focus up and down the data structure resembles the operation of a zipper on a regular pair of pants.

A zipper data structure represents a hole. We have the current focus represented as tree, but everything else that can construct the entire tree back up is also preserved. To create TreeLoc call loc method on a Tree:

TreeLoc implements various methods to move the focus around, similar to DOM API:

sealedtrait TreeLoc[A]{
...
/** Select the parent of the current node. */def parent: Option[TreeLoc[A]]= ...
/** Select the root node of the tree. */def root: TreeLoc[A]= ...
/** Select the left sibling of the current node. */def left: Option[TreeLoc[A]]= ...
/** Select the right sibling of the current node. */def right: Option[TreeLoc[A]]= ...
/** Select the leftmost child of the current node. */def firstChild: Option[TreeLoc[A]]= ...
/** Select the rightmost child of the current node. */def lastChild: Option[TreeLoc[A]]= ...
/** Select the nth child of the current node. */def getChild(n: Int): Option[TreeLoc[A]]= ...
/** Select the first immediate child of the current node that satisfies the given predicate. */def findChild(p: Tree[A]=> Boolean): Option[TreeLoc[A]]= ...
/** Get the label of the current node. */def getLabel: A = ...
...
}

Note getChild returns an Option[TreeLoc[A]] so we need to use monadic chaining >>=, which is the same as flatMap. The odd thing is that getChild uses 1-based index! There are various methods to create a new TreeLoc with modification, but useful looking ones are:

/** Modify the current node with the given function. */def modifyTree(f: Tree[A]=> Tree[A]): TreeLoc[A]= ...
/** Modify the label at the current node with the given function. */def modifyLabel(f: A => A): TreeLoc[A]= ...
/** Insert the given node as the last child of the current node and give it focus. */def insertDownLast(t: Tree[A]): TreeLoc[A]= ...

More readable, I guess, but it does take up lines so it's case by case.

This is pretty much the end of Learn You a Haskell for Great Good. It did not cover everything Scalaz has to offer, but I think it was an exellent way of gently getting introduced to the fundamentals. After looking up the corresponding Scalaz types for Haskell
types, I am now comfortable enough to find my way around the source code and look things up as I go.

Anyway, let's see some of the typeclasses that we didn't have opportunity to cover.

Id

The Identity monad is a monad that does not embody any computational strategy. It simply applies the bound function to its input without any modification. Computationally, there is no reason to use the Identity monad instead of the much simpler act of simply applying functions to their arguments. The purpose of the Identity monad is its fundamental role in the theory of monad transformers. Any monad transformer applied to the Identity monad yields a non-transformer version of that monad.

Here's the corresponding type in Scalaz:

/** The strict identity type constructor. Can be thought of as `Tuple1`, but with no
* runtime representation.
*/type Id[+X]= X

We need to look at monad transformer later, but one thing that's interesting is that all data types can be Id of the type.