Search code examples
clojureclojure-core.typed

What is the correct type annotation for this function?


I've got the following utility function, which should be self explanatory:

(ns my.utility-belt
  "Use this everywhere."
  (:use clojure.core.typed))

(ann  zipfn (All [c a b ...] [[a b ... b -> c] (Seqable a) * -> (Seqable c)]))
(defn zipfn
  "Applies f to the interleaved elements of colls. If 2 colls are given, then f
  will recieve 2 arguments, one from each coll. If 3 colls are given, then f
  will receive 3 arguments, and so on. Returns a flat sequence of the results of
  applying f to its args."
  [f & colls]
  (map (partial apply f) (partition (count colls) (apply interleave colls))))

(comment
  (let [c1 [1 2 3 4 5]
        c2 [5 4 3 2 1]]
    (assert (= (zipfn * c1 c2)
               '(5 8 9 8 5)))))

The annotation I've provided isn't entirely correct, but I have no idea why. Calling (check-ns) just gives me "Type Error (my/utility_belt.clj:12:51) Bad arguments to polymorphic function in apply in (apply interleave colls)"

What's the correct type annotation in this case?


Solution

  • The problem is core.typed is having trouble inferring this is the actual type of zipfn. The quickest way to get around this is to tell core.typed to ignore the definition of zipfn with :no-check.

    (ann ^:no-check zipfn (All [c a b ...] [[a b ... b -> c] (Seqable a) * -> (Seqable c)]))