Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure.typed basics

I've started playing with the seemingly quite impressive clojure.typed library, but very shortly after I run into problems, even when trying to apply it to simple functions. Does anyone have experience with the library?

Problem 1

(typed/ann square [Double -> Double])
(defn square "Square of"
  [num]
  (* num  num))

Type Error (clojure_study/ideas/swarm/vector_algebra.clj:15:3) Return type of static method clojure.lang.Numbers/multiply is java.lang.Long, expected java.lang.Double.

Problem 2

(typed/defalias CartesianVector '{:x Double :y Double})
(typed/ann v+ [CartesianVector * -> CartesianVector])
(defn v+ "Sum vector of vectors"
  [& vectors]
  (apply merge-with + vectors))

Type Error (clojure_study/ideas/swarm/vector_algebra.clj:28:3) Bad arguments to polymorphic function in apply in: (apply merge-with + vectors)

Problem 3

(typed/ann v- [CartesianVector CartesianVector -> CartesianVector])
(defn v- "Diff vector of vectors"
  [v1 v2]
  (merge-with - v1 v2))

Type Error (clojure_study/ideas/swarm/vector_algebra.clj:33:3) Polymorphic function merge-with could not be applied to arguments: Polymorphic Variables: k v

Thanks for any help offered.

like image 660
Máté Magyari Avatar asked Feb 02 '15 08:02

Máté Magyari


People also ask

Is Clojure typed?

Clojure is dynamically and strongly typed. PHP is dynamically and weakly typed. Haskell is statically and strongly typed. Java, as the most design-by-committe language ever, manages to be a mix of all four.

Is Clojure faster than Python?

I also have published load test results of these microservices at http://glennengstrand.info/software/performance/eks/gke where you will find the per minute average throughput for these two microservices to be about the same but the clojure version was about twice as slow as the python version.

How hard is Clojure?

clojure is hard to learn. very hard. Forget about fan boy things you've heard.


1 Answers

Your answer is now 3 years old, so this may not be much help, but I was using Typed Clojure in a big production codebase around the same time and have some experience with it. Also, the answers that weavejester provided in your Reddit thread on the topic are pretty much spot-on, so I'm just going to re-summarize them here to save future visitors the inconvenience of having to click another link.

In general your approach is correct at a high level but you're running into areas in which core.typed simply didn't (and maybe still doesn't) know how to behave smartly.

Here's what's going on:

Problem 1

This should probably be considered a bug on the behalf of core.typed, because there is a function signature supporting Double as a return type. You can circumvent this by using clojure.lang.Number or clojure.core.typed/Num instead, both of which encompass both Long and Double.

Problem 2

This is just a syntax error - that's not how you specify maps to core.typed. You should be using an HMap instead:

(t/defalias CartesianVector
  (t/HMap :mandatory {:x t/Num, :y t/Num} :complete? true))

Problem 3

Unfortunately core.typed cannot successfully infer that merge-with (a core function) when applied to two maps of the same type will return a map of the same type. This is a limit of the type-checker. You can get around this by re-writing your function to explicitly merge rather than relying on merge-with:

(defn v-
  [{x1 :x, y1 :y} {x2 :x, y2 :y}]
  {:x (- x1 x2), :y (- y1 y2)})
like image 56
Venantius Avatar answered Oct 12 '22 12:10

Venantius