Clojure Core.Typed for apply for apply

时间:2014-01-20 18:28:02

标签: clojure clojure-core.typed

我再次通过项目euler来开发和磨练我的核心技能。但是我理解类型检查器的输出有很多困难。我在阅读了几篇关于core.typed的介绍性资料以及关于core.typed wiki的一些信息之后问我。

我正在使用以下代码,请注意apply的注释以及num对函数euler3中输入的映射无效。仍会生成错误消息。请忽略明显不良的factorsprime?函数。我选择了天真的实现,让我专注于类型注释。

(ns euler-clj.euler3
"Project euler problem 3.
 Uses a very naive prime tester, would use a sieve or probabilistic
 prime algorithm for a larger problem set.
 What is the largest prime factor of the number 600851475143?"

(:require [clojure.core.typed :refer
          [ann check-ns Int fn> non-nil-return Seq cf]]
          [euler-clj.euler1 :as e1]))

(non-nil-return clojure.lang.Numbers/quotient :all)
(ann ^:no-check clojure.core/apply [[Number Number * -> Number] (Seq Number) -> Number])

(ann factors [Int -> (Seq Int)])
(defn factors
  [n]
  (filter (fn> [m :- Int] (e1/div-by m n)) (range 1 (inc (quot n 2)))))

; Very bad prime function, should be sieve/probabilistic.
; Also identifies 1 as prime incorrectly.
(ann prime? [Int -> Boolean])
(defn prime? [n] (= [1] (factors n)))

(ann euler3 [Int -> Number])
(defn euler3
  [n]
  (apply max (map num (filter prime? (factors n)))))

(ann -main [-> nil])
(defn -main
  []
  (prn (euler3 600851475143)))

这会产生以下错误:

Type Error (euler-clj.euler3:26:3) Bad arguments to apply: 

Target:         (Fn [java.lang.Number java.lang.Number * -> java.lang.Number])

Arguments:      (clojure.core.typed/Seq java.lang.Number)
in: (clojure.core/apply clojure.core/max (clojure.core/map clojure.core/num (clojure.core/filter euler-clj.euler3/prime?
 (euler-clj.euler3/factors n))))


ExceptionInfo Type Checker: Found 1 error  clojure.core/ex-info (core.clj:4327)
Start collecting euler-clj.euler3
Start collecting euler-clj.euler1
Finished collecting euler-clj.euler1
Finished collecting euler-clj.euler3
Collected 2 namespaces in 62.584894 msecs
Start checking euler-clj.euler1
Checked euler-clj.euler1 in 165.76663 msecs
Start checking euler-clj.euler3
Checked euler-clj.euler3 in 200.997234 msecs
Checked 2 namespaces (approx. 60 lines) in 430.302357 msecs

我需要提供哪些类型的注释才能申请接受最大数量,然后接受这个数字序列?

由于

1 个答案:

答案 0 :(得分:2)

首先,您不应为apply提供自己的类型;它是在类型检查器中作为特殊情况实现的。

在这种情况下,core.typed需要一些说服力,max永远不会被零参数调用。

这是一种方法:

(ann euler3 [Int -> Number])
(defn euler3
  [n]
  (let [[f & r] (map num (filter prime? (factors n)))]
    (if f
      (apply max f r)
      (throw (Exception. "No prime factors")))))