progs/dfa.scala
changeset 504 5dc452d7c08e
parent 487 a697421eaa04
child 576 550186034b6e
--- a/progs/dfa.scala	Tue Sep 26 14:07:29 2017 +0100
+++ b/progs/dfa.scala	Tue Sep 26 14:08:49 2017 +0100
@@ -1,64 +1,65 @@
-// DFAs
-import scala.util._
+// DFAs in Scala  using partial functions
+import scala.util.Try
+
+// type abbreviation for partial functions
+type :=>[A, B] = PartialFunction[A, B]
 
-abstract class State
-type States = Set[State]
+case class DFA[A, C](start: A,               // starting state
+                     delta: (A, C) :=> A,    // transition (partial fun)
+                     fins:  A => Boolean) {  // final states
 
-case class IntState(i: Int) extends State
+  def deltas(q: A, s: List[C]) : A = s match {
+    case Nil => q
+    case c::cs => deltas(delta(q, c), cs)
+  }
+
+  def accepts(s: List[C]) : Boolean = 
+    Try(fins(deltas(start, s))) getOrElse false
+}
 
-object NewState {
-  var counter = 0
-  
-  def apply() : IntState = {
-    counter += 1;
-    new IntState(counter - 1)
-  }
-}
+// the example shown in the handout 
+abstract class State
+case object Q0 extends State
+case object Q1 extends State
+case object Q2 extends State
+case object Q3 extends State
+case object Q4 extends State
+
+val delta : (State, Char) :=> State = 
+  { case (Q0, 'a') => Q1
+    case (Q0, 'b') => Q2
+    case (Q1, 'a') => Q4
+    case (Q1, 'b') => Q2
+    case (Q2, 'a') => Q3
+    case (Q2, 'b') => Q2
+    case (Q3, 'a') => Q4
+    case (Q3, 'b') => Q0
+    case (Q4, 'a') => Q4
+    case (Q4, 'b') => Q4 }
+
+val dfa = DFA(Q0, delta, Set[State](Q4))
+
+dfa.accepts("bbabaab".toList)   // true
+dfa.accepts("baba".toList)      // false
 
 
-// DFA class
-case class DFA(states: States, 
-               start: State, 
-               delta: (State, Char) => State, 
-               fins: States) {
-  
-  def deltas(q: State, s: List[Char]) : State = s match {
-    case Nil => q
-    case c::cs => deltas(delta(q, c), cs) 
-  }
-  
-  // wether a string is accepted by the automaton or not
-  def accepts(s: String) : Boolean = 
-    Try(fins contains 
-      (deltas(start, s.toList))) getOrElse false
-}
-
+// another DFA test with a Sink state
+abstract class S
+case object S0 extends S
+case object S1 extends S
+case object S2 extends S
+case object Sink extends S
 
-// example DFA from the lectures
-val Q0 = NewState()
-val Q1 = NewState()
-val Q2 = NewState()
-val Q3 = NewState()
-val Q4 = NewState()
-
+// transition function with a sink state
+val sigma : (S, Char) :=> S = 
+  { case (S0, 'a') => S1
+    case (S1, 'a') => S2
+    case _ => Sink
+  }
 
-val delta : (State, Char) => State = {
-  case (Q0, 'a') => Q1
-  case (Q0, 'b') => Q2
-  case (Q1, 'a') => Q4
-  case (Q1, 'b') => Q2
-  case (Q2, 'a') => Q3
-  case (Q2, 'b') => Q2
-  case (Q3, 'a') => Q4
-  case (Q3, 'b') => Q0
-  case (Q4, 'a') => Q4
-  case (Q4, 'b') => Q4
-}
+val dfa1a = DFA(S0, sigma, Set[S](S2))
 
-val DFA1 = DFA(Set(Q0, Q1, Q2, Q3, Q4), Q0, delta, Set(Q4))
+dfa1a.accepts("aa".toList)        // true
+dfa1a.accepts("".toList)          // false
+dfa1a.accepts("ab".toList)        // false
 
-println(DFA1.accepts("aaa"))
-println(DFA1.accepts("bb"))
-println(DFA1.accepts("aaac"))
-
-