如何在Haskell中表示有限自动机?它的数据类型会是什么样子?
在我们学院,自动机被定义为一个5元组
(Q, X, delta, q_0, F)
其中Q为自动机的状态集,X是字母表(这部分是否必要尚不确定),delta是从(Q,X)取2元组并返回状态/-s(在非确定性版本中)的转移函数,F是接受/结束状态的集合。
最重要的是,我不确定delta
应该具有什么类型...
如何在Haskell中表示有限自动机?它的数据类型会是什么样子?
在我们学院,自动机被定义为一个5元组
(Q, X, delta, q_0, F)
其中Q为自动机的状态集,X是字母表(这部分是否必要尚不确定),delta是从(Q,X)取2元组并返回状态/-s(在非确定性版本中)的转移函数,F是接受/结束状态的集合。
最重要的是,我不确定delta
应该具有什么类型...
delta :: Q -> X -> Q
(或适当的[Q]
)。delta :: Map (Q, X) Q
,例如使用Data.Map
,或者如果您的状态/字母表可以按升序编号,则使用Data.Array
或Data.Vector
。请注意,这两种方法本质上是等效的,可以相对容易地从映射版本转换为函数版本(由于lookup
调用中的额外Maybe
略有不同)。
delta_func q x = Data.Map.lookup (q,x) delta_map
(或者使用适合您使用的映射类型的经过适当柯里化的查找函数版本。)请查看“arrows”包中的Control.Arrow.Transformer.Automaton模块。类型如下:
newtype Automaton a b c = Automaton (a b (c, Automaton a b c))
type Auto = Automaton (->)
这里使用函数作为基础箭头。在自动机定义中用(->)代替"a",并使用中缀符号可以看出它大致等同于:
newtype Auto b c = Automaton (b -> (c, Auto b c))
state1, state2 :: Auto Char Bool
state1 c = if c == 'a' then (False, state2) else (False, state1)
state2 c = case c of
'a' -> (False, state2)
'b' -> (True, state1)
otherwise -> (False, state1)
关于你最初的问题,Q = {state1, state2},X = Char,delta 是函数应用,F 是状态转换返回True的输出转换(而不是使用“接受状态”,我使用了一个具有接受值的输出转换)。
或者你可以使用箭头符号。自动机是所有有趣的箭头类的实例,包括Loop和Circuit,因此您可以通过使用delay来访问先前的值。(注意:再次未经测试的代码)
recognise :: Auto Char Bool
recognise = proc c -> do
prev <- delay 'x' -< c -- Doesn't matter what 'x' is, as long as its not 'a'.
returnA -< (prev == 'a' && c == 'b')
-- | Inputs are accumulated, but decay over time. Input is a (time, value) pair.
-- Output is a pair consisting
-- of the previous output decayed, and the current output.
decay :: (ArrowCircuit a) => NominalDiffTime -> a (UTCTime, Double) (Double, Double)
decay tau = proc (t2,v2) -> do
rec
(t1, v1) <- delay (t0, 0) -< (t2, v)
let
dt = fromRational $ toRational $ diffUTCTime t2 t1
v1a = v1 * exp (negate dt / tau1)
v = v1a + v2
returnA -< (v1a, v)
where
t0 = UTCTime (ModifiedJulianDay 0) (secondsToDiffTime 0)
tau1 = fromRational $ toRational tau
F
可以实现为isEnd :: Q -> Bool
。 - Sjoerd Visscher