В файле подписи F# каково значение круглых скобок вокруг подписи функции?

#f#

Вопрос:

Как пользователь файла подписи .fsi, какая разница, если таковая имеется, существует между:

 val sum : int -> int -> int
 

и

 val sum : (int -> int -> int)
 

Похоже, что второе может быть реализовано с помощью определения функции или с помощью псевдонима функции, но первое может быть реализовано только с помощью определения функции.

Со следующими:

 // .fsi
val add : int -> int -> int
val sum : int -> int -> int
 
 // .fs
let add a b = a   b
let sum = add
 

генерируется ошибка

 error FS0034: Module 'Butter' contains
    val sum : (int -> int -> int)
but its signature specifies
    val sum : int -> int -> int    
 

однако, если файл подписи является:

 // .fsi
val add : (int -> int -> int)
val sum : (int -> int -> int)
 

он компилируется нормально.

Является ли такое поведение преднамеренным, и если да, то как круглые скобки изменяют интерфейс?

Ответ №1:

Что здесь за Кортеж? Если это .NET System.Tuple , то это не имеет смысла.

 val x : Tuple -> float
 

Будет функцией, которая принимает кортеж статического класса и возвращает значение с плавающей точкой. Если вам нужен экземпляр кортежа, вам нужно будет точно указать, какой тип n-кортежа вы хотите ( Tuple<'a> и Tuple<'a, 'b> это два разных типа).

Должно сработать следующее:

 var x : Tuple<float, _, _, _> -> float

 

Комментарии:

1. Спасибо тебе, Том. Мое включение Tuple в пример делает излишне запутанным, что этот кортеж является типом домена, не связанным с кортежами языка. Но чтобы дважды проверить, что это не проблема, и чтобы уменьшить путаницу, я воссоздал проблему с помощью гораздо более простого кода. Я обновлю свой вопрос и тоже планирую загрузить демо-код. (Исходный код предназначен для «Задачи трассировки лучей».) Спасибо.

Ответ №2:

Да, это преднамеренное поведение.

Создавая более простой пример в ответ на ответ Тома, я на самом деле правильно прочитал сообщение об ошибке, в котором говорится:

Различия в подписи и реализации различаются. Подпись указывает, что «сумма» — это определение функции или лямбда-выражение, принимающее по крайней мере 2 аргумента(аргумента), но реализация представляет собой вычисленное значение функции. Чтобы объявить, что вычисляемое значение функции является разрешенной реализацией, просто заключите его тип в скобки в подписи, например↔ сумма значений: int -> (int ->> int)↔вместо↔ сумма значений: int ->>> int ->>>> int.

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