core.typed

Support a Path Element for first/second/nth

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

What I tried:

(def-alias Statement
  (U
   '[':params String]
   '[':no-params]))

(ann unpack-vector [Statement -> Any])
(defn unpack-vector [stmt]
  (let [key (first stmt)]
    (if (= :params key)
      (let [param (second stmt)]
        (ann-form param String)))))

I expected this to type-check. Instead, I got:

Type Error (typed_mm/core.clj:14:9) Local binding param__#0 expected type java.lang.String, but actual type (t/Option (U (Value :params) (Value :no-params) String))
in: param
 
 
Type Error (typed_mm/core.clj:14:19) Type mismatch:
 
Expected: 	java.lang.String
 
Actual: 	(t/Option (U (Value :params) (Value :no-params) String))
in: param

I could understand core.typed thinking it could be `nil` if it looked at both members of the union, but it is very strange to me that it thinks the second item in the vector could be :params or :no-params, as those should only occur in the first position...

(With version 0.2.45-20140511.165157-12)

Activity

Hide
Jake Goulding added a comment -

It's actually the same for heterogenous maps as well:

(def-alias Statement
  (U (HMap :mandatory {:op ':params
                       :val String}
           :complete? true)
     (HMap :mandatory {:op ':no-params}
           :complete? true ) ))

(ann unpack-map [Statement -> Any])
(defn unpack-map [stmt]
  (let [key (:op stmt)]
    (if (= :params key)
      (let [param (:val stmt)]
        (ann-form param String)))))

With error:

Type Error (NO_SOURCE_FILE:13:9) Local binding param__#0 expected type java.lang.String, but actual type (U nil String)
in: param

Type Error (NO_SOURCE_FILE:13:19) Type mismatch:

Expected:       java.lang.String

Actual:         (U nil String)
in: param
Show
Jake Goulding added a comment - It's actually the same for heterogenous maps as well:
(def-alias Statement
  (U (HMap :mandatory {:op ':params
                       :val String}
           :complete? true)
     (HMap :mandatory {:op ':no-params}
           :complete? true ) ))

(ann unpack-map [Statement -> Any])
(defn unpack-map [stmt]
  (let [key (:op stmt)]
    (if (= :params key)
      (let [param (:val stmt)]
        (ann-form param String)))))
With error:
Type Error (NO_SOURCE_FILE:13:9) Local binding param__#0 expected type java.lang.String, but actual type (U nil String)
in: param

Type Error (NO_SOURCE_FILE:13:19) Type mismatch:

Expected:       java.lang.String

Actual:         (U nil String)
in: param
Hide
Jake Goulding added a comment -

Perhaps this isn't something that's possible right now? As a human, I know that (:op stmt) can only take one of two values, each of which uniquely picks between the union values. I think this would involve changing variable stmt based on information from key, which I have yet to find in the source code.

Show
Jake Goulding added a comment - Perhaps this isn't something that's possible right now? As a human, I know that (:op stmt) can only take one of two values, each of which uniquely picks between the union values. I think this would involve changing variable stmt based on information from key, which I have yet to find in the source code.
Hide
Ambrose Bonnaire-Sergeant added a comment -

I don't expect the HVec case to work yet.

I explain how it might be implemented from [12:01:38] http://logs.lazybot.org/irc.freenode.net/%23typed-clojure/2014-05-11.txt

The HMap case also fails for me. Looks like core.typed is sensitive to order or something, because rearranging it like this checks fine:

(ns clojure.core.typed.test.hmap-branch
  (:require [clojure.core.typed :as t]))

(t/def-alias Statement
  (U (HMap :mandatory {:op ':params
                       :val String}
           :complete? true)
     (HMap :mandatory {:op ':no-params}
           :complete? true ) ))

(t/ann unpack-map2 [Statement -> Any])
(defn unpack-map2 [stmt]
  (when (= (:op stmt) :params)
    (let [param (:val stmt)]
      (t/ann-form param String))))
Show
Ambrose Bonnaire-Sergeant added a comment - I don't expect the HVec case to work yet. I explain how it might be implemented from [12:01:38] http://logs.lazybot.org/irc.freenode.net/%23typed-clojure/2014-05-11.txt The HMap case also fails for me. Looks like core.typed is sensitive to order or something, because rearranging it like this checks fine:
(ns clojure.core.typed.test.hmap-branch
  (:require [clojure.core.typed :as t]))

(t/def-alias Statement
  (U (HMap :mandatory {:op ':params
                       :val String}
           :complete? true)
     (HMap :mandatory {:op ':no-params}
           :complete? true ) ))

(t/ann unpack-map2 [Statement -> Any])
(defn unpack-map2 [stmt]
  (when (= (:op stmt) :params)
    (let [param (:val stmt)]
      (t/ann-form param String))))
Hide
Jake Goulding added a comment -

Added a patch with some initial refactoring to cleanup the implementation of check.nth. Useful implementation is still being worked on.

Show
Jake Goulding added a comment - Added a patch with some initial refactoring to cleanup the implementation of check.nth. Useful implementation is still being worked on.
Hide
Ambrose Bonnaire-Sergeant added a comment -

Merged. I also made the overlap case more accurate: https://github.com/clojure/core.typed/commit/623bfe0918036ea8aa1f5496e268d8b1dfdf0db5

Thanks!

Show
Ambrose Bonnaire-Sergeant added a comment - Merged. I also made the overlap case more accurate: https://github.com/clojure/core.typed/commit/623bfe0918036ea8aa1f5496e268d8b1dfdf0db5 Thanks!

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: