Clojure Core.Typed适用于apply的注释

3
我正在重新学习 Project Euler 来提高和锤炼我的核心类型化技能。然而,我很难理解类型检查器的输出。在阅读了几篇 core.typed 的入门材料以及一些 core.typed wiki 上的信息后,我仍然不明白。

我使用以下代码,请注意,在函数 euler3 中,对apply的注释以及将num映射到输入中均无效。仍会生成错误消息。请忽略明显错误的 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)))

这将产生以下错误:
类型错误(euler-clj.euler3:26:3)apply的参数无效:
目标: (Fn [java.lang.Number java.lang.Number * -> java.lang.Number])
参数: (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 类型检查错误:发现1个错误 clojure.core/ex-info (core.clj:4327) 开始搜集euler-clj.euler3 开始搜集euler-clj.euler1 完成收集euler-clj.euler1 完成收集euler-clj.euler3 在62.584894毫秒内收集了2个命名空间 开始检查euler-clj.euler1 在165.76663毫秒内检查了euler-clj.euler1 开始检查euler-clj.euler3 在200.997234毫秒内检查了euler-clj.euler3 在430.302357毫秒内检查了2个命名空间(大约60行)

为了让 apply 接受 max 和这些数字序列,我需要提供什么类型注释?

谢谢

1个回答

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")))))

嗨,Ambrose,非常感谢你的回复,一旦你指出来,答案就变得相当明显了。哈哈。我十分确定 apply 有一个内置的注解,但是当您尝试为大多数核心函数进行注释时,似乎不会收到关于重复注释的警告。是否有某些原因导致某些功能会发出警告而另一些则不会? - Cody
apply 没有基础注释可以依赖,因此用户添加的任何注释可能是唯一存在的注释。我们可以给 apply 一些可能的注释,每种注释都有不同的优缺点。 - Ambrose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接