2014-02-10 43 views
4

我想獲得clojure.core.typed類型的檢查傳遞,但是我收到了一個我不明白的類型錯誤。這個clojure.core.typed類型錯誤是什麼意思?

我的問題是:

  • 是什麼下面的錯誤是什麼意思?
  • 我該如何解決?

這裏是我的代碼(我知道是不正確的):

(ns clj.util.map 
    (:require [clojure.core.typed :as t])) 

(t/ann map-vals 
     (All [k v1 v2] 
      (Fn [ (Fn [(t/Option v1) -> (t/Option v2)]) 
        (t/Option (t/Map k v1)) -> 
        (t/Option (t/Map k v2)) ]))) 

(defn map-vals 
    ;; FIXME: Incorrect code 
    "Apply a function to each of the values in a map, returning the updated map." 
    [f hm] 
    (t/doseq> [k :- Any (keys hm)] 
      (assoc hm k (f (get hm k))))) 

這裏是lein typed check clj.util.map輸出:

Initializing core.typed ... 
"Elapsed time: 6697.604 msecs" 
core.typed initialized. 
Start collecting clj.util.map 
Finished collecting clj.util.map 
Collected 1 namespaces in 6851.111 msecs 
Start checking clj.util.map 
Checked clj.util.map in 968.041 msecs 
Checked 1 namespaces (approx. 21 lines) in 7823.552 msecs 
Type Error (clj.util.map:14:23) Polymorphic function clojure.core/keys could not be applied to arguments: 
Polymorphic Variables: 
    k 

Domains: 
    (t/Map k Any) 

Arguments: 
    (t/Option (t/Map k v1)) 

Ranges: 
    (t/Seq k) :object {:path [Keys], :id 0} 

in: (clojure.core/keys hm) 
in: (clojure.core/seq (clojure.core/keys hm)) 


Type Checker: Found 1 error 
Found errors 
Subprocess failed 

回答

13

錯誤的第一部分告訴你這涉及致電clojure.core/keys。你可以用(cf keys)查找類型。

(All [k] [(Map k Any) -> (Seq k) :object {:id 0 :path [Keys]}])

的誤差基本上總結了此多態性類型與提供給該函數的實際類型並置。

Polymorphic Variables列出了All活頁夾及其類型界限中的所有變量。 k是唯一的變量,它基本上沒有界限,所以顯示k

Domains按順序列出所有參數類型(在->的左邊)。如果使用Fn指定了多個字段,則將按順序顯示每個參數列表。

Arguments告訴你什麼類型的實際傳遞給函數。在14:23的代碼大概是這個調用(keys hm),所以顯示的第一個參數的類型:(t/Option (t/Map k v1))

Ranges列表中的所有返回類型(在->的右)的順序。

有時是Expected類型,必須以同樣的方式全部Arguments必須了一個Domain匹配了Range熱身賽。

我們可以通過比較DomainsArguments來診斷此錯誤。 Arguments的列表必須符合Domains的一個列表,並且匹配嘗試自頂向下。如果沒有Domains符合Arguments,我們會得到這樣的類型錯誤;精確定位約束算法失敗的位置通常太複雜,因此用戶會看到很多信息。

在這種情況下,我們嘗試將(t/Option (t/Map k v1))的參數設置爲(t/Map k Any),即失敗。這是因爲參數(t/Option (t/Map k v1))(U nil (t/Map k v1))相同,並且nil不適用於域(t/Map k Any)

有幾種方法可以解決這個問題。您基本上需要確保keys未通過nil。這裏有一個選項:

(keys (or hm {}))

+1

很好的解釋;總是有意義的。感謝你,併爲'clojure.core.typed'的出色工作! –