我应该写一些haskell程序,但我真的不知道从哪里开始。如果你能给我一些资源来阅读或解释我的问题,我将非常感激。我确信这是一个非常业余的东西,但我真的需要一个起点。
data DFA q o = DFA (q -> o -> q) q [q]
data NFA q o = NFA (q -> o -> [q]) [q] [q]
-- I really realy don't understand the declarations here
-- I can guess that q is somewhat related to Q and o to E, but don't get what it really means
data Q = Q0 | Q1 | Q2
deriving (Eq, Enum, Bounded)
data E = A | B
-- what does n1 do ??
n1 :: NFA Q E
n1 = NFA d [Q0] [Q2] -- i see [Q0] refers to set of initial states and [Q2] refers to final states :)
where
d Q0 A = [Q0]
d Q0 B = [Q0, Q1]
d Q1 _ = [Q2]
d Q2 _ = []
-- the following functions are for me to write
starDFA :: Eq q => DFA q o -> [o] -> Bool
--for the above function, what are the arguments the function takes in ?
--how can we relate q with Q and [o] with [E] ??
对正确起点的任何解释或引用对我都非常有帮助。 很抱歉问这么愚蠢的问题,但我真的不知道从哪里开始:)
由于
答案 0 :(得分:17)
Learn You a Haskell for Great Good!可能是目前最好的Haskell教程。我建议阅读整篇文章,但如果你赶时间,我会指出一些更相关的部分。
您获得的代码中的主要部分是data
声明,因此,一旦您熟悉基础知识(chapter 2和first section of chapter 3),这是一个潜水的好地方in是Algebraic data types intro,Type variables和Type parameters。
上述内容足以破译数据声明并理解q
与Q
和o
与E
之间的关系。
现在要实现实际的功能,你需要熟悉deterministic finite automata如何工作,然后知道足够的Haskell来编写实际的实现。 Chapter 4和chapter 5是本教程中最相关的章节,您可能还会发现section on standard library list functions很有用。
一旦你达到这一点,如果你坚持实施,你可以用你迄今为止编写的代码发布另一个问题。
答案 1 :(得分:6)
在haskell中,我们有三种方式来定义新类型,使用三个不同的关键字,类型, newtype 和数据。
在您的示例中,正在使用的数据关键字,让我们更多地关注它。
最好从代码
data E = A | B
在这里,我们定义了一个新类型E,它只能采用两个模式或状态或值。
像这样的类型就是我们所说的和类型。
我们怎么能用呢?
主要是模式匹配。
useE :: E -> String
useE A = "This is A"
useE B = "This is B"
现在,您的代码中的数据声明更复杂。
data Q = Q0 | Q1 | Q2 deriving (Eq, Enum, Bounded)
同样,如前所述,我们有一个和类型,它定义了一个新类型Q,取三个值,Q0,Q1或Q2。但是我们有一个派生子句,它告诉编译器这个新类型实现了从 Eq,Enum,Bounded class 派生(或继承)的方法(或函数)。
这是什么意思?
我们来看一个函数
想象一下,您想要为Q的每个值关联一个数字,我们如何才能执行该操作?
enumQ :: Q -> Int
enumQ x = fromEnum x
如果您想通过派生子句提供有关此特定功能的更多信息,请阅读已指明的资源并尝试ghci下的:info Enum 。请注意,以前的类型也可以派生自同一个类。由于这些类型被完全描述为可枚举值集合的总和(由 | 区分),我们更好地理解为什么我们将它们称为 sum类型。
最后是最困难的数据声明。
data DFA q o = DFA (q -> o -> q) q [q]
data NFA q o = NFA (q -> o -> [q]) [q] [q]
如果事实上它们几乎是相同的数据定义那么我将通过第一个数据定义,并让你分析第二个作为练习。
data DFA q o = DFA (q -> o -> q) q [q]
这次我们必须讨论数据构造函数和类型构造函数。
现在请记住,以下是类型,
然后我们的数据声明(在此上下文中)是数据构造函数,由两个类型参数 q 和 o 提供,并且结果,它返回一个新类型作为高阶函数的基本类型和列表类型的乘积。这解释了为什么我们称之为产品类型。
现在,应该自己推断,回答你的问题 n1是什么?
祝你好运。答案 2 :(得分:3)
从我对Haskell类型声明的了解很少,关于DFA和NFA的初始陈述就是这样的(例如,查看NFA):
(左侧:) NFA是一种在其结构中使用两种类型(q和o)的类型。
(右侧:) NFA的一个实例将被称为NFA,并由三个参数组成:
(1)“(q - &gt; o - &gt; [q])”,表示一个函数,它接受两个参数,一个是q型,一个是o类型,并返回q的列表,([q])<登记/>
(2)“[q]”,表示q类型的一个值列表
(3)“[q]”,另一个类型的值列表q
n1似乎是NFA的实例构造,我们看到了
n1 = NFA d [Q0] [Q2]
所以我们可以推断出:
(1)d是一个带有两个参数的函数,'q'和'o'并返回q的列表
(2)[Q0]是q的列表,和
(3)[Q2]是q的列表。
确实,d的定义如下:
d采用两个参数,一个'Q'和一个'E',并返回一个Q列表(我们知道可以是Q0,Q1或Q2) )或空名单。
我希望这有点帮助,或者也许有人可以澄清和纠正我的模糊理解。