diff -r f2d7b885b3e3 -r 5dc452d7c08e progs/dfa.scala --- 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")) - -