Types (对我来说)令人惊讶的简单F#函数类型

Types (对我来说)令人惊讶的简单F#函数类型,types,f#,Types,F#,我正在编写一个F#函数,如下所示,用于计算数字列表与累加器“r”的乘积 令我惊讶的是,根据F#console的说法,它的proda类型是: val proda : xs:int list -> r:int -> int 为什么proda的类型不是 val proda : xs:a' list -> r:a' -> a' 参数的类型被推断为int,因为您正在使用*运算符聚合x*r中的列表元素。这将x和r的类型确定为int,因此,xs将变为int list 如果您想避免这

我正在编写一个F#函数,如下所示,用于计算数字列表与累加器“r”的乘积

令我惊讶的是,根据F#console的说法,它的
proda
类型是:

val proda : xs:int list -> r:int -> int
为什么
proda的类型不是

val proda : xs:a' list -> r:a' -> a'

参数的类型被推断为
int
,因为您正在使用
*
运算符聚合
x*r
中的列表元素。这将
x
r
的类型确定为
int
,因此,
xs
将变为
int list

如果您想避免这种情况,可以将
*
替换为作为额外参数提供的函数:

let rec proda f xs r =
  match xs with
  | [] -> r
  | x::xr -> proda f xr (f x r) 
它具有以下类型:

val proda : f:('a -> 'b -> 'b) -> xs:'a list -> r:'b -> 'b
这是一个非常有用的函数,它恰好作为
列表包含在核心F#library中。fold
(最后两个参数已切换)!它更一般,因为结果的类型可能与列表中的元素不同(
a
vs.
b
),但它只是对您所拥有内容的简单概括

编辑您是对的,
*
也可以与
浮动
一起使用。要支持这一点,您必须使函数
内联
。这有点棘手,因为您无法使用递归函数执行此操作,因此需要添加嵌套的递归函数:

让内联proda xs r=
让rec循环xs r=
将xs与
|[]->r
|x::xr->loop xr(x*r)
循环XSR
使用内联函数,编译器可以推断“静态成员约束”,这本质上是一种表示“支持
*
的任何类型”的方式。语法有点冗长:

val inline proda :
  xs: ^a list -> r: ^b ->  ^b
    when ( ^a or  ^b) : (static member ( * ) :  ^a *  ^b ->  ^b)

参数的类型被推断为
int
,因为您正在使用
*
运算符聚合
x*r
中的列表元素。这将
x
r
的类型确定为
int
,因此,
xs
将变为
int list

如果您想避免这种情况,可以将
*
替换为作为额外参数提供的函数:

let rec proda f xs r =
  match xs with
  | [] -> r
  | x::xr -> proda f xr (f x r) 
它具有以下类型:

val proda : f:('a -> 'b -> 'b) -> xs:'a list -> r:'b -> 'b
这是一个非常有用的函数,它恰好作为
列表包含在核心F#library中。fold
(最后两个参数已切换)!它更一般,因为结果的类型可能与列表中的元素不同(
a
vs.
b
),但它只是对您所拥有内容的简单概括

编辑您是对的,
*
也可以与
浮动
一起使用。要支持这一点,您必须使函数
内联
。这有点棘手,因为您无法使用递归函数执行此操作,因此需要添加嵌套的递归函数:

让内联proda xs r=
让rec循环xs r=
将xs与
|[]->r
|x::xr->loop xr(x*r)
循环XSR
使用内联函数,编译器可以推断“静态成员约束”,这本质上是一种表示“支持
*
的任何类型”的方式。语法有点冗长:

val inline proda :
  xs: ^a list -> r: ^b ->  ^b
    when ( ^a or  ^b) : (static member ( * ) :  ^a *  ^b ->  ^b)

谢谢然而“*”并不限于整数。它也适用于浮子!例如,“funx->x*2.8”是float->float类型的函数,刚刚发现“funxy->x*y”是“int->int->int”类型。惊讶。你是对的-你可以使用
内联
使
*
同时使用浮点和整数。见编辑,谢谢。然而“*”并不限于整数。它也适用于浮子!例如,“funx->x*2.8”是float->float类型的函数,刚刚发现“funxy->x*y”是“int->int->int”类型。惊讶。你是对的-你可以使用
内联
使
*
同时使用浮点和整数。请参见编辑。