There is no better way to understand path dependent types and their importance in Scala other than by directly looking at the problem that they help us solve.
Let us implement a very simple Lock/Key using Scala.
We defined a Lock and a Key class. You need a key to open a lock. Looks neat! Lets use it..
The usage also looks quite simple. A lock is opened using a key. But there is no restriction on which Key is required to open a Lock. This is not normal.
A red key is capable of opening a blue lock! There should be a way to prevent such misuse. Path dependent types to the rescue!! We will rewrite our implementation of Lock and Key and the difference between the two is quite subtle. Key class is defined inside the Lock class. This binds each instance of Key to specific instance of Lock.
The above implementation of Lock fixes the problem that we had. Now a lock can be opened only by a key of its type. The Key class above is a path dependent type. A blue-lock requires a blue-lock.key type. Using Key from some other Lock gives a compile time error and hence avoids possible disaster scenarios at run time.
And that’s pretty much it..Path-dependent may not be always present in our Scala code, they do have a lot of practical values. One of their most important usage is with cake pattern. Cake Pattern helps us achieve dependency injection in “scala way”. See the excellent articles by Debasish Ghosh and Precog’s Daniel Spiewak to learn more about both the cake pattern and how it can be improved by incorporating path-dependent types.