在F#的函数签名中定义元组数据类型

时间:2018-12-12 15:41:11

标签: f# tuples

我想定义一个元组元素的预期数据类型,该数据类型将传递给调用函数。当我不定义它并让类型推断起作用时,这是可以的,但此刻我想编写仍然在任何地方都未调用的小函数,我不知道如何定义参数。

这个例子。我希望description是一个元组,其中五个元素中的每个元素都是一个int,然后提取每个要使用的部分。

let setArray (description: int * int * int * int * int)  =
    let id = fun (i, _, _, _, _) -> i
    let startX = fun (_, x, _, _, _) -> x
    let startY = fun (_, _, y, _, _) -> y
    let width = fun (_, _, _, w, _) -> w
    let height = fun (_, _, _, _, h) -> h
    let arrayResult = Array2D.init (width + 1) (height + 1) (fun i j -> if i < width &&  j < height then id)
    arrayResult
  

.fsx(29,45):错误FS0001:类型'int'与类型'a *'b *'c *'d *'e->'d'

不匹配

对于其他功能,就像我说的那样,类型推断是有效的,我可以毫无问题地使用模式匹配

let getMaxCoords =
    let x = elements |> Seq.map (fun (_, x, _, _, _) -> x) |> Seq.max
    let y = elements |> Seq.map (fun (_, _, y, _, _) -> x) |> Seq.max
    x, y

我在做什么错了?

1 个答案:

答案 0 :(得分:4)

首先,以下代码块定义了五个函数,而不是五个整数值:

let setArray (description: int * int * int * int * int)  =
    let id = fun (i, _, _, _, _) -> i
    let startX = fun (_, x, _, _, _) -> x
    let startY = fun (_, _, y, _, _) -> y
    let width = fun (_, _, _, w, _) -> w
    let height = fun (_, _, _, _, h) -> h

您可能想要做的是将description元组传递给每个解构函数,如下所示:

let setArray (description: int * int * int * int * int)  =
    let id = description |> (fun (i, _, _, _, _) -> i)
    let startX = description |> (fun (_, x, _, _, _) -> x)
    let startY = description |> (fun (_, _, y, _, _) -> y)
    let width = description |> (fun (_, _, _, w, _) -> w)
    let height = description |> (fun (_, _, _, _, h) -> h)

但是有一种更简单的方法可以做到这一点。 F#使您可以破坏函数签名中的元组。因此,您可以使用以下代码替换整个代码块:

let setArray (id, startX, startY, width, height) =

就是这样!所以现在您的整个功能如下:

let setArray (id, startX, startY, width, height) =
    let arrayResult = Array2D.init (width + 1) (height + 1) (fun i j -> if i < width && j < height then id)
    arrayresult

您还可以进行另一种简化。每当您在let x = (some calculation)之后紧跟着x作为函数的返回值时,就可以摆脱该let,而让函数返回(some calculation)。应用这种简化,您的功能将变为:

let setArray (id, startX, startY, width, height) =
    Array2D.init (width + 1) (height + 1) (fun i j -> if i < width && j < height then id)

您完成了!如果您确实要指定idstartX等都是整数,则可以这样做:

let setArray (id : int, startX : int, startY : int, width : int, height : int) =
    Array2D.init (width + 1) (height + 1) (fun i j -> if i < width && j < height then id)