Functional logic languages are a high-level approach to programming by combining the most important declarative features. They abstract from small-step operational details so that programmers can concentrate on the logical aspects of an application. This is supported by appropriate evaluation strategies. Demand-driven evaluation from functional programming is amalgamated with non-determinism from logic programming so that solutions or values are computed whenever they exist. This frees the programmer from considering the influence of an operational strategy on the success of a computation, but it is a challenge to the language implementer. A non-deterministic demand-driven strategy might duplicate unevaluated choices of an expression, which could duplicate the computational effort. In recent implementations, this problem has been tackled by adding a kind of memoization of non-deterministic choices to the expression under evaluation. Since this has been implemented in imperative target languages, it was unclear whether this could also be supported in a functional programming environment like Haskell. This paper presents a solution to this challenge by transforming functional logic programs into a monadic representation. Although this transformation is not new, we present an implementation of the monadic interface which supports memoization in non-deterministic branches. Additionally, we include more advanced features of functional logic languages, namely functional patterns and encapsulated search, in our approach. By optimizing our implementation for purely functional computations with both a static and dynamic approach, we are able to achieve a promising performance that outperforms current compilers for Curry.
翻译:函数式逻辑语言通过结合最关键的声明式特性,提供了一种高级编程方法。它们抽象掉了小步操作细节,使程序员能够专注于应用的逻辑层面,这一特性通过适当的求值策略得以支持。函数式编程中的需求驱动求值与逻辑编程中的非确定性相融合,使得只要存在解或值就能进行计算,从而免去了程序员考虑操作策略对计算成功影响的负担,但这给语言实现者带来了挑战。非确定性的需求驱动策略可能复制未求值的表达式选择,从而导致计算开销的重复。在近期的实现中,这一问题通过向被求值表达式添加一种非确定性选择的记忆化机制得到了解决。由于这已在命令式目标语言中实现,此前尚不清楚是否也能在类似Haskell的函数式编程环境中支持。本文提出了一种解决方案,通过将函数式逻辑程序转换为单子表示来解决这一挑战。尽管这一转换并非新方法,但我们实现了一种支持非确定性分支中记忆化的单子接口。此外,我们在方法中纳入了函数式逻辑语言的更高级特性,即函数式模式和封装搜索。通过采用静态和动态两种方式优化面向纯函数式计算的实现,我们取得了优于当前Curry编译器的性能表现。