Newbie f# question
I have a simple function开发者_如何学C 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!
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 )
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)
.
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 )
精彩评论