F#如何编写一个带有int列表或字符串列表的函数

gre*_*gyb 11 f#

我在F#中弄乱,试图编写一个可以带a int list或a 的函数string list。我编写了一个逻辑上通用的函数,其中我只能修改参数的类型,并且只能同时使用两种类型的列表。但是我不能一概而论地定义两者兼而有之。

这是我的函数,没有类型注释:

let contains5 xs =
    List.map int xs
    |> List.contains 5
Run Code Online (Sandbox Code Playgroud)

当我尝试对函数进行注释以采用通用列表时,会收到警告FS0064: the construct causes the code to be less generic than indicated by the type annotations。从理论上讲,我不需要对此进行注释即可,但是无论如何我还是尝试过。

我可以将其编译为两个单独的文件,其中一个

let stringtest = contains5 ["1";"2";"3";"4"]
Run Code Online (Sandbox Code Playgroud)

和另一个

let inttest = contains5 [1;2;3;4;5]
Run Code Online (Sandbox Code Playgroud)

在每个这些文件中,编译成功。或者,我可以将函数定义和测试之一发送给解释器,然后类型推断就可以了。如果我尝试编译或将函数定义以及这两个测试发送给解释器,则会收到error FS0001: This expression was expected to have type string, but here has type int

我是否误解打字应该如何工作?我有一个函数,其代码可以处理整数列表或字符串列表。我可以用任何一个成功地测试它。但是我不能在同时处理两者的程序中使用它吗?

Cur*_*ols 7

您可以使用inline防止将函数固定为特定类型。

在FSI中,交互式REPL:

> open System;;
> let inline contains5 xs = List.map int xs |> List.contains 5;;
val inline contains5 :
  xs: ^a list -> bool when  ^a : (static member op_Explicit :  ^a -> int)

> [1;2;3] |> contains5;;
val it : bool = false

> ["1";"2";"5"] |> contains5;;
val it : bool = true
Run Code Online (Sandbox Code Playgroud)

请注意,contains5的签名具有通用元素。这里有更多关于内联函数的信息


Ste*_*eve 7

您正在运行到该类型推理系统的自动推广价值限制,概括这里

特别,

情况4:添加类型参数。

解决方案是使函数通用,而不仅仅是使其参数通用。

let inline contains5< ^T when ^T : (static member op_Explicit: ^T -> int) > (xs : ^T list)  =
    List.map int xs
    |> List.contains 5
Run Code Online (Sandbox Code Playgroud)

您必须使函数内联,因为必须使用静态解析的类型参数,并且必须使用静态解析的类型参数才能使用成员约束来指定类型必须可转换为int。作为概述这里