Created
March 14, 2016 02:38
-
-
Save tel/2992dcbbff7af053bc55 to your computer and use it in GitHub Desktop.
Beautiful "Graphs" signature example from Martin Odersky's "Scala: The Simple Parts"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Partially (!) specializes Graphs signature. | |
* | |
* Note that Node and Edge are still abstract! We add new | |
* functionality by concretely specifying Graph, but the DSL | |
* still works in its limited initial form since newGraph abstracted | |
* over Graph construction | |
* | |
*/ | |
trait AbstractModel extends Graphs { | |
class Graph(val nodes: Set[Node], val edges: Set[Edge]) extends GraphSig { | |
def outgoing(n: Node) = edges filter (pred(_) == n) | |
def incoming(n: Node) = edges filter (succ(_) == n) | |
lazy val sources = nodes filter (incoming(_).isEmpty) | |
} | |
def newGraph(nodes: Set[Node], edges: Set[Edge]) = new Graph(nodes, edges) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Here we make a totally orthogonal specialization | |
*/ | |
trait ConcreteModel extends Graphs { | |
type Node = Person | |
type Edge = (Person, Person) | |
def succ(e: Edge) = e._1 | |
def pred(e: Edge) = e._2 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Signature defines an entire graph manipulation library/DSL! | |
*/ | |
trait Graphs { | |
type Node | |
type Edge | |
// Ambient combinators (not very OO!) | |
def pred(e: Edge): Node | |
def succ(e: Edge): Node | |
// Rich domain object inherits from its own signature (not very ML!) | |
type Graph <: GraphSig | |
def newGraph(nodes: Set[Node], edges: Set[Edge]): Graph | |
trait GraphSig { | |
def nodes: Set[Node] | |
def edges: Set[Edge] | |
def outgoing(n: Node): Set[Edge] | |
def incoming(n: Node): Set[Edge] | |
def sources: Set[Node] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Finally, here's a totally concrete implementation "for free" | |
*/ | |
class MyGraph extends ConcreteModel with AbstractModel |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment