Более короткий способ ограничить функцию

Я ищу более короткий способ (если он есть) для ограничения функции. Например.

let inline sincos (a:'T) =
    let y = sin a
    let x = cos a
    y, x

Для использования этой функции 'T должен поддерживать как Sin, так и Cos статические элементы. Я могу ограничить его работу с float32 с помощью:

let sincosf = sincos : float32 -> float32 -> float32

или используя подстановочный знак:

let sincosf = sincos : float32 -> _

Мой вопрос в том, можно ли добавить параметр типа к sincos, поэтому мне просто нужно написать:

let sincosf = sincos<float32>

Заранее спасибо.


person Stringer    schedule 13.12.2010    source источник


Ответы (1)


Действительно, let sincosf = sincos<float32> выдаст вам предупреждение, но будет работать как есть.

Как я отметил в комментариях, должна быть возможность явно указать параметр типа в определении sincos, который удалит предупреждение. Однако это также требует, чтобы все предполагаемые ограничения для этого параметра были указаны, что может быть немного некрасиво. В этом случае компилятор F# все равно неожиданно отклоняет определение:

let inline sincos< ^t when ^t : (static member Sin : ^t -> ^t)
                       and ^t : (static member Cos : ^t -> ^t)> (a: ^t) =
  let y = sin a
  let x = cos a
  y, x

Я считаю, что это ошибка компилятора.

person kvb    schedule 13.12.2010
comment
Можно ли объявить sincos с явным параметром типа 'T, чтобы предупреждение исчезло? - person Tim Robinson; 13.12.2010
comment
В чем причина такого предупреждения? - person Stephen Swensen; 13.12.2010
comment
@Tim - это должно быть возможным; однако вам также необходимо явно включить ограничения. Когда я пытаюсь сделать это для этого примера, компилятор F# становится неожиданно недовольным... - person kvb; 13.12.2010
comment
@kvb Правильно; Я не могу понять правильный синтаксис для общих ограничений. - person Tim Robinson; 13.12.2010
comment
@kvb: Спасибо за ответ. Также, если у меня есть несколько аргументов (например, sincos (a:'T) (b:'T) = ...), я получаю предупреждение FS0686: The method or function 'sincos' should not be given explicit type argument(s) because it does not declare its type parameters explicitly. Как вы думаете, возможно ли удалить их с явными ограничениями? - person Stringer; 13.12.2010
comment
@Stringer Bell - да, вероятно, можно будет удалить предупреждение, но это будет зависеть от ограничений (из-за ошибок компилятора). - person kvb; 13.12.2010
comment
@kvb: я думаю, что знаю, почему явные ограничения здесь не работают: числа с плавающей запятой и двойники на самом деле не имеют статических членов Sin и Cos. sin и cos используют трюк оператора case только для компилятора F #, чтобы вызывать System.Math.Sin /Cos перегружается по мере необходимости (см. prim-types.fs). - person Stephen Swensen; 13.12.2010
comment
@Stephen - хотя эти члены имитируются, сбой происходит во время определения универсального метода sincos, который не ссылается на какие-либо конкретные типы. - person kvb; 13.12.2010
comment
@kvb: ах, верно. Но я все еще думаю, что это основная причина ошибки; компилятор, даже несмотря на то, что он дает сигнатуры смоделированного типа, которые заставляют вас поверить, что Sin и Cos являются просто обычными статическими ограничениями типа члена, знает, что они смоделированы, а ограничение статического члена ^t, указанное в этом явном ограничении, не соответствует смоделированному статическому ограничению. для Sin/Cos. Например, попробуйте заменить let y... на let y = (^T : (static member Sin : ^T -> ^T) (a)) и то же самое на let x.... Функция компилируется, но с предупреждением об особенностях Sin/Cos. - person Stephen Swensen; 13.12.2010
comment
... и вы больше не можете использовать sincos с float/float32, поскольку он, по-видимому, знает разницу между смоделированными и не смоделированными ограничениями статического члена Sin/Cos. - person Stephen Swensen; 13.12.2010
comment
... ну, на самом деле, вы можете использовать его с float/float32 (он скомпилируется), но это приведет к ошибке времени выполнения. - person Stephen Swensen; 13.12.2010
comment
@Stephen - да, это кажется правдоподобным объяснением существования ошибки; к сожалению, смоделированные члены довольно часто необходимы при использовании inline определений. В ответ на мой отчет об ошибке Дон Сайм предположил, что для решения проблемы можно использовать файлы сигнатур. - person kvb; 13.12.2010