新手f#问题

时间:2010-10-07 20:12:52

标签: f# types tuples

我有一个简单的函数调用需要两个元组。在类型上获取编译器错误:

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 )

错误2“float”类型与“int16”

类型不匹配

不确定哪里出错了。有人可以帮忙吗?

谢谢!

3 个答案:

答案 0 :(得分:6)

Math.Sqrt期望float的参数,但你传递int16。 F#不执行此类隐式转换

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

或者你可以从一开始就传递花车:

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 )

答案 1 :(得分:6)

正如其他人已经指出的那样,F#编译器不会自动在数值类型之间插入任何转换。这意味着如果你正在编写一个与浮点数一起工作的函数,你需要将它作为参数传递给浮点数。

您的示例中的函数可以使用各种类型,因为Math.Sqrt和数字运算符会重载。如果您在没有任何类型注释的情况下编写它,您将获得一个使用浮点数的函数(因为Math.Sqrt仅适用于浮点数):

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

这只能以floats作为参数调用,因此您需要像Joel建议的那样调用它。如果要获取一个将其他类型的数字作为参数的函数,则需要添加类型注释和转换。我会这样写:

> 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

我们只需要一个类型的注释(然后编译器会发现y1x2,...也必须是int16类型,因为我们正在增加/添加它们,只允许两个相同类型的值)。所以,现在你可以写:

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

请注意,desco的版本有点棘手 - 它添加了转换(使用float)函数,但它没有类型注释来指定参数的类型 - 在这种情况下,编译器将选择默认类型,即int,因此如果您使用他的功能,则必须使用side (2,3) (1,2)来调用它。

答案 2 :(得分:3)

您的函数的签名是float * float -> float * float -> float,但您传递的是int16值(这就是s后缀的含义)。

将其编译的一种方法是执行此操作:

let a = side ( 2.0, 3.0 ) ( 1.0, 2.0 )