tags:

views:

127

answers:

3
+3  Q: 

Newbie f# question

I have a simple function call takes two tuples. Getting compiler error on type:

module test

open System.IO
open System

let side (x1,y1) (x2,y2) : float = 
  Math.Sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))

let a = side ( 2s, 3s ) ( 1s, 2s )

Error 2 The type 'float' does not match the type 'int16'

Not sure where it goes wrong. Can anyone help?

Thanks!

+3  A: 

The signature of your function is float * float -> float * float -> float but you're passing in int16 values (that's what the s suffix means).

One way to get it to compile would be to do this:

let a = side ( 2.0, 3.0 ) ( 1.0, 2.0 )
Joel Mueller
+5  A: 

Math.Sqrt expects argument of float, but you pass there int16. F# doesn't perform such implicit conversions

let side (x1,y1) (x2,y2) : float = 
    (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)
    |> float
    |> Math.Sqrt

or you can pass floats from the very beginning:

let side (x1,y1) (x2,y2) : float = Math.Sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))

let a = side ( 2.0, 3.0 ) ( 1.0, 2.0 )
desco
+6  A: 

As others already pointed out, the F# compiler doesn't automatically insert any conversions between numeric types. This means that if you're writing a function that works with floats, you need to pass it floats as arguments.

The function in your example can work with various types, because Math.Sqrt and numeric operators are overloaded. If you write it without any type annotations, you'll get a function working with floats (because Math.Sqrt only works with floats):

> let side (x1,y1) (x2,y2) = 
    Math.Sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));;
val side : float * float -> float * float -> float

This can be called only with floats as arguments, so you need to call it like Joel suggests. If you want to get a function that takes other type of number as parameter, you'll need to add type annotations and conversion. I would write it like this:

> let side (x1:int16,y1) (x2,y2) = 
    let n = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)
    Math.Sqrt(float(n));;
val side : int16 * int16 -> int16 * int16 -> float

We need only a single type annotation (the compiler then figures out that y1, x2, ... also have to be of type int16, because we're multiplying/adding them and that's only allowed on two values of the same type). So, now you can write:

side ( 2s, 3s ) ( 1s, 2s ) 

Note that the version by desco is a bit tricky - it adds conversion (using the float) function, but it doesn't have type annotation to specify the type of parameters - in this case, the compiler will pick a default type which is int, so if you use his function, you'll have to call it using side (2,3) (1,2).

Tomas Petricek