Определение типов данных кортежа в сигнатуре функции на F # - PullRequest
0 голосов
/ 12 декабря 2018

Я хочу определить ожидаемый тип данных элементов кортежа, которые будут переданы для вызова функции.Когда я не определяю это и позволяю выводу типа работать, это нормально, но сейчас я хочу написать небольшие функции, которые до сих пор нигде не вызываются, и я не понимаю, как определить аргументы.

Это пример.Я ожидаю, что 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'

Для других функций, таких как Iсказал, что вывод типа работает, и я могу использовать сопоставление с образцом без проблем

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 голосов
/ 12 декабря 2018

Во-первых, следующий блок кода определяет пять функций , а не пять целочисленных значений:

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)

И все готово!Если вы действительно хотите указать, что id, startX и т. Д. Являются целыми числами, вы можете сделать это следующим образом:

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)
...