News for hackers. Stuff that matters.
Re:A Year in Clojure by StreamBright on Sunday October 07, 2018 @11:33AM (#18161041)
It is funny, I usually know what I am getting in this function in my Clojure code. OCaml (or Haskell) gives entirely different comfort to me, it tells me what makes sense as input and output type for my function. The downside is that I need to define different functions for different types.

utop # let avg a b = (a +. b) /. 2.0;;

val avg : float -> float -> float = <fun>

utop # avg 2 4;;

Error: This expression has type int but an expression was expected of type float

utop # avg 2.0 4.0;;

- : float = 3.

user=> (defn avg [a b] (/ (+ a b) 2))

#'user/avg

user=> (avg 2 4) 3

user=> (avg 2.0 4.0) 3.0

I think it is a matter of taste which one you prefer. With property based testing and specs you can go very far in term of pre-runtime checks and there was some data about the number of bugs per line published by Github where it turned out that Clojure did not do too bad in comparison to statically typed languages.

Re:A Year in Clojure by ff_ on Sunday October 07, 2018 @11:43AM (#18161105)
I don't know about OCaml, but Haskell has typeclasses (which look like "polymorphic interfaces"?) so you can define functions generically and put a typeclass constraint to make them work on a certain class of types. E.g. your avg function would be of type:

avg :: Num a => a -> a -> a

Where your "a" is a number (that is, a type that implements the Num typeclass)

This would work out of the box on floats, ints, etc

Re:A Year in Clojure by StreamBright on Sunday October 07, 2018 @01:03PM (#18161552)
The signature is not really helpful. Can you show me how do you implement the actual function?

If you have operators that are typed like + and +. how can you make this work with Num?

Re:A Year in Clojure by ff_ on Sunday October 07, 2018 @01:16PM (#18161603)
Also the + operator is typed with Num; from a Haskell repl:

  λ> :t (+)
  (+) :: Num a => a -> a -> a
In case of average we need /:

  λ> :t (/)
  (/) :: Fractional a => a -> a -> a
So our type is going to be constrained by Fractional instead of Num). So an implementation could be (from here [1]):

  import Data.List
  average :: (Real a, Fractional b) => [a] -> b
  average xs = realToFrac (sum xs) / genericLength xs
[1]: https://stackoverflow.com/questions/2376981