我是学生,在我的编程课程中,我们必须学习Haskell。所以我是新手,我没有那么多的经验。我也不熟悉在论坛上发帖。
首先,我将发布图书馆,我必须与之合作。 (DA:确定性自动机)
type State = Integer
type DA = (State, State -> Char -> State, State -> Bool)
type ListDA = (State, [((State, Char), State)], [State])
a :: DA
a = (0, delta, (==1))
where
delta 0 'a' = 1
delta 1 'a' = 1
delta 2 'a' = 1
delta 0 'b' = 2
delta 1 'b' = 2
delta 2 'b' = 2
toDA :: ListDA -> DA
toDA (start, delta, final) = (start, deltaFun delta, (`elem` final))
where deltaFun dl = curry (fromMaybe 0 . flip lookup dl)
toDA函数在其列表表示中采用自动机并将其转换为自动机。该功能和图书馆的其余部分由讲座主席提供。
现在的问题是写一个类型为
的函数advance :: DA -> State -> String -> State
此函数接受自动机,状态和字符串,并在读取字符串后返回自动机的状态。
到目前为止,这个想法很清楚。 DA类型的自动机具有状态转换函数delta。所以功能"推进"必须以某种方式调用delta函数。但是如何访问集成在类型中的函数?
答案 0 :(得分:4)
您可以使用模式匹配:
advance :: DA -> State -> String -> State
advance (start, step, accept) fromState chars = ....
type
关键字只介绍type synonyms。 DA
只是三重(Integer, Integer -> Char -> Integer, Integer -> Bool)
的同义词。
您的命名令人困惑。 delta
自动机定义中的a
是状态转换函数,但在toDA
函数的定义中,名为delta
的参数是一个列表。 ListDA
类型也只是三元组的同义词(不同的一个 - 状态,转换列表和可接受状态列表)。
以下是使用递归for循环编码的方法:
advance (_, step, _) fromState chars = go fromState chars
where
go s [] = ... -- stop, and produce the state as the answer,
-- when the input string (list of chars) has ended
go s (c:cs) = -- if not, then
let s2 = step s c -- make one step
in go ....... -- and loop with new values
请注意,我们不需要start
或accept
变量,因此我们可以在那里使用匿名变量模式_
。此外,step
是类型State -> Char -> State
的函数,它指示函数调用中使用的参数的顺序。即它接受一个州和一个角色,并产生一个新的状态。
如果您根本不了解Haskell,您可能会从阅读(并完成)一个好的教程like this one中受益。
最后,既然你说你“不熟悉在论坛上发帖”,请一般性地阅读accepting answers和FAQ。
答案 1 :(得分:3)
在您评估函数之前,函数与Haskell中的任何其他类型的数据实际上没有任何不同 - 此时全局定义的函数,通过模式匹配获得的函数变量或未命名的函数之间没有任何区别拉姆达。
在这种情况下,正如Will Ness所说,通过名称上的模式匹配来获取函数是最容易的,
advance (start, delta, terminate) = result
然后,您可以在此范围内使用delta
和terminate
,就像其他任何功能一样:
where result = delta start 'b' -- or whatever, conditional on terminate...