Haskell中的Prolog类型层次结构

Haskell中的Prolog类型层次结构,haskell,types,prolog,Haskell,Types,Prolog,我目前正在努力使用Parsec在Haskell中构建一个Prolog。虽然我对Haskell的了解充其量也不多,但Parsec的承诺和强大的类型系统足以吸引我 我首先按照类型层次结构来映射语言,从文字原语、原子、变量到抽象规则、Head、子句 infix 6 :- data Program = Program [ProExp] data ProExp = ProExp Fact | Rule data Fact = Fact Head data Rule = Rul

我目前正在努力使用Parsec在Haskell中构建一个Prolog。虽然我对Haskell的了解充其量也不多,但Parsec的承诺和强大的类型系统足以吸引我

我首先按照类型层次结构来映射语言,从文字原语、原子、变量到抽象规则、Head、子句

infix 6 :-
data Program   = Program [ProExp]
data ProExp    = ProExp Fact | Rule
data Fact      = Fact Head
data Rule      = Rule Head Body
data Body      = Clauses [Clause] | Link Char
data Head      = Head Clause
data Clause    = Clause Predicate Terms
data Goals     = Goals [Predicates]
data Predicate = Predicate String
data Terms     = Terms [Term]
data Term      = Constant String
               | Variable String
使用的术语遵循Clocksin的条款和效力


如何以有利于使用Parsec的方式改进此类型系统?为此,请分享对我的设计选择的任何批评。

总体而言,这种方法非常好。事实上,Haskell和其他函数式语言非常适合这一点。一些警告:

这些类型中的一些似乎并不真正有用,例如,如果我定义了术语,它将是一个类型同义词type Terms=[Term],而不是data,我更喜欢使用[Term]

对于单字段单构造函数类型,通常使用newtype而不是data,除非您确实需要额外的惰性

Prolog中的子句引用您所称的ProExp:事实或规则。正如在1中一样,我不会将事实和规则划分为不同的类型,而只是子句的构造函数:

甚至可能仅仅是data子句=事实{head::Callable}规则{head::Callable,body::[Callable]},但是head在实际实现Prolog时可能很有用。或者完全删除事实,因为它基本上只是一个空主体的规则,一旦你们开始实施事情

总的来说,你可能想刷新你的记忆,而不是尽你所能地工作


总的来说,这种方法非常好。事实上,Haskell和其他函数式语言非常适合这一点。一些警告:

这些类型中的一些似乎并不真正有用,例如,如果我定义了术语,它将是一个类型同义词type Terms=[Term],而不是data,我更喜欢使用[Term]

对于单字段单构造函数类型,通常使用newtype而不是data,除非您确实需要额外的惰性

Prolog中的子句引用您所称的ProExp:事实或规则。正如在1中一样,我不会将事实和规则划分为不同的类型,而只是子句的构造函数:

甚至可能仅仅是data子句=事实{head::Callable}规则{head::Callable,body::[Callable]},但是head在实际实现Prolog时可能很有用。或者完全删除事实,因为它基本上只是一个空主体的规则,一旦你们开始实施事情

总的来说,你可能想刷新你的记忆,而不是尽你所能地工作


看起来不错,但对于这样一个FAQ站点来说,这不是一个好问题-似乎有点自以为是。我会编写类型Program=[ProExp],类型Fact=Head,类型Rule=Head,Body等等。制作所有数据都会导致大量的样板文件。类型和数据之间的区别在于类型引入了同义词,而数据引入了新的数据类型,因此,例如,当程序是类型而不是数据时,您可以将映射应用于程序。即使你真的想要一种新的数据类型,你的大多数数据也应该被新类型所取代。我不确定这是否太有用。毕竟,你只有条件,没有别的。例如,规则是一个带有functor:-/2的术语。术语很容易建模。但是,您需要定义计算查询的语义。例如,Term1和Term2的语义是什么?你到底怎么处理这个逗号呢?这是一个控制谓词,但它也是术语语法的一部分。@Carsten你建议我如何构建我的问题以引出更客观的答案?只是要明确一点:Prolog程序可以被视为纯数据。经典Prolog程序的结构非常简单:它是一个无序的谓词集合;每个谓词都是子句的有序集合。每个子句都是嵌套的术语。就是这样。除此之外,如果您希望能够评估查询,则必须添加证明策略。在您的问题中,您已经在数据模型中添加了太多不必要的细节,这可能是因为您试图太接近术语。仅我的$0.02.看起来不错,但对于这样的FAQ站点来说,这不是一个好问题-似乎有点自以为是。我会编写类型Program=[ProExp],类型Fact=Head,类型Rule=Head,Body等等。制作所有数据都会导致大量的样板文件。类型和数据之间的区别在于类型引入了同义词,而数据引入了新的数据类型,因此,例如,当程序是类型而不是数据时,您可以将映射应用于程序。即使你真的想要一种新的数据类型,你的大多数数据也应该被新类型所取代。我不确定这是否太有用。毕竟,你只有条件,没有别的。例如,规则是一个带有functor:-/2的术语。条件很简单
我们应该做榜样。但是,您需要定义计算查询的语义。例如,Term1和Term2的语义是什么?你到底怎么处理这个逗号呢?这是一个控制谓词,但它也是术语语法的一部分。@Carsten你建议我如何构建我的问题以引出更客观的答案?只是要明确一点:Prolog程序可以被视为纯数据。经典Prolog程序的结构非常简单:它是一个无序的谓词集合;每个谓词都是子句的有序集合。每个子句都是嵌套的术语。就是这样。除此之外,如果您希望能够评估查询,则必须添加证明策略。在您的问题中,您已经在数据模型中添加了太多不必要的细节,这可能是因为您试图太接近术语。就我的0.02美元。我不太确定这整件事,包括事实与规则的区别。毕竟,你只有条件。规则就是术语:-/2,例如:--fooX,barX。一个术语是事实还是谓词的子句取决于它是否被计算。我不太确定这整件事,包括事实与规则的区别。毕竟,你只有条件。规则就是术语:-/2,例如:--fooX,barX。一个术语是事实还是谓词的子句取决于它是否被计算。
data Clause = Fact Head | Rule Head Body