Factorial in Clojure core.logic



我想使用core.logic编写阶乘

factorial(0, 1).
factorial(N, M):- N1 is N - 1, factorial (N1, M1), M is N*M1.

并尝试以以下方式将其翻译为core.logic

(defne factorialo [n m]
  ([0 1])
  ([n m] (fresh [n1 m1]
            (== (- n 1) n1)
            (== (* n m1) m)
            (factorialo n1 m1))))
(run* [q]
  (factorialo 3 q))

其以消息失败

clojure.core.logic.LVar cannot be cast to java.lang.Number
  [Thrown class java.lang.ClassCastException]

在core.logic中写阶乘的正确方法是什么?

Prolog中的算术通常意味着隐式投影-您不再与逻辑变量进行关系处理,而是与它们绑定的实际值进行关系处理。在core.logic中,这还没有好的糖。您必须使投影显式:

(defne factorialo [n m]
  ([0 1])
  ([n m]
     (fresh [n1 m1]
       (project [n]
         (== n1 (- n 1)))
       (factorialo n1 m1)
       (project [n m1]
         (== m (* n m1))))))
(run 1 [q]
  (factorialo 3 q))

在core.logic 0.8.0 alphas中,支持有限域上的约束逻辑编程。这改进了Prolog的算术故事:

(defne factorialfd [n m]
  ([0 1])
  ([n m]
     (fresh [n1 m1]
       (infd n1 m1 (interval 0 Integer/MAX_VALUE))
       (+fd n1 1 n)
       (factorialfd n1 m1)
       (*fd n m1 m))))
(run 1 [q]
  (infd q (interval 0 Integer/MAX_VALUE))
  (factorialfd 3 q))

请注意,变量的域必须明确,但我们不再需要为投影而烦恼。然而,这项工作是非常重要的,这种解决方案在未来的样子可能会发生变化。

最新更新