build (r1 :&: r2) sigma = do
  lbfa1 <- build r1 sigma
  lbfa2 <- build r2 sigma
  let minS1 = firstState lbfa1
      minS2 = firstState lbfa2
      name (s1,s2) = (lastState lbfa2 - minS2 +1) *
                     (s1 - minS1) + s2 - minS2 + minS1
      nS = name (lastState lbfa1,lastState lbfa2) +1
      transInit = (nS, [ (a, name (s1, s2))
                       | (a,s1) <- transitionList
                                   lbfa1 (initial lbfa1)
                       , (b,s2) <- transitionList
                                   lbfa2 (initial lbfa2)
                       , a == b])
      transTable = [(name (s1, s2),
                     [(a, name (s3, s4))
                     | (a,s3)   <- tl1
                     , (b,s4)   <- tl2, a == b ])
                   | (s1,tl1) <- trans lbfa1
                   , (s2,tl2) <- trans lbfa2
                   , s1 /= initial lbfa1 || s2 /= initial lbfa2 ]
      transUnion = transInit:transTable
      fs  = [ nS | acceptEpsilon lbfa1 && acceptEpsilon lbfa2 ]
            ++ 
            [ name (f1,f2) | f1 <- finals lbfa1, f2 <- finals lbfa2 ]
  put (nS + 1)
  return LBFA {
    trans  = merge [ (s, []) | s <- fs ] transUnion,
    finalS = fs,
    alpha  = sigma,
    initS  = nS,
    lastS  = nS
   }
build (r1 :&: r2) sigma = do
  lbfa1 <- build r1 sigma
  lbfa2 <- build r2 sigma
  let minS1 = firstState lbfa1
      minS2 = firstState lbfa2
      name (s1,s2) = (lastState lbfa2 - minS2 +1) *
                     (s1 - minS1) + s2 - minS2 + minS1
      nS = name (lastState lbfa1,lastState lbfa2) +1
      transInit = (nS, [ (a, name (s1, s2))
                       | (a,s1) <- transitionList
                                   lbfa1 (initial lbfa1)
                       , (b,s2) <- transitionList
                                   lbfa2 (initial lbfa2)
                       , a == b])
      transTable = [(name (s1, s2),
                     [(a, name (s3, s4))
                     | (a,s3)   <- tl1
                     , (b,s4)   <- tl2, a == b ])
                   | (s1,tl1) <- trans lbfa1
                   , (s2,tl2) <- trans lbfa2
                   , s1 /= initial lbfa1 || s2 /= initial lbfa2 ]
      transUnion = transInit:transTable
      fs  = [ nS | acceptEpsilon lbfa1 && acceptEpsilon lbfa2 ]
            ++ 
            [ name (f1,f2) | f1 <- finals lbfa1, f2 <- finals lbfa2 ]
  put (nS + 1)
  return LBFA {
    trans  = merge [ (s, []) | s <- fs ] transUnion,
    finalS = fs,
    alpha  = sigma,
    initS  = nS,
    lastS  = nS
   }
build (r1 :&: r2) sigma = do
  lbfa1 <- build r1 sigma
  lbfa2 <- build r2 sigma
  let minS1 = firstState lbfa1
      minS2 = firstState lbfa2
      name (s1,s2) = (lastState lbfa2 - minS2 +1) *
                     (s1 - minS1) + s2 - minS2 + minS1
      nS = name (lastState lbfa1,lastState lbfa2) +1
      transInit = (nS, [ (a, name (s1, s2))
                       | (a,s1) <- transitionList
                                   lbfa1 (initial lbfa1)
                       , (b,s2) <- transitionList
                                   lbfa2 (initial lbfa2)
                       , a == b])
      transTable = [(name (s1, s2),
                     [(a, name (s3, s4))
                     | (a,s3)   <- tl1
                     , (b,s4)   <- tl2, a == b ])
                   | (s1,tl1) <- trans lbfa1
                   , (s2,tl2) <- trans lbfa2
                   , s1 /= initial lbfa1 || s2 /= initial lbfa2 ]
      transUnion = transInit:transTable
      fs  = [ nS | acceptEpsilon lbfa1 && acceptEpsilon lbfa2 ]
            ++ 
            [ name (f1,f2) | f1 <- finals lbfa1, f2 <- finals lbfa2 ]
  put (nS + 1)
  return LBFA {
    trans  = merge [ (s, []) | s <- fs ] transUnion,
    finalS = fs,
    alpha  = sigma,
    initS  = nS,
    lastS  = nS
   }