Types (对我来说)令人惊讶的简单F#函数类型
我正在编写一个F#函数,如下所示,用于计算数字列表与累加器“r”的乘积 令我惊讶的是,根据F#console的说法,它的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 如果您想避免这
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”类型。惊讶。你是对的-你可以使用内联使*
同时使用浮点和整数。请参见编辑。