2009-10-01 3 views
9

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

Что это должно быть как:

 
let sqrt (x : float<'u^2>) = 
    let x' = x/1.0<'u^2> // Delete unit 
    (x ** 0.5) * 1.0<'u>  // Reassign unit 

Но это отвергается из-за ненулевые константы не разрешено иметь общие единицы.

Есть ли способ написать эту функцию? С встроенным sqrt он отлично работает, и какая магия он выполняет?

+1

Связанный вопрос: (также ответил @kvb) http://stackoverflow.com/questions/1398611/f-ununit-reunit-inside-a-function – Benjol

ответ

6

Разрешение ненулевых общих констант позволило бы очень легко нарушить безопасность системы типов для блоков (см. Статью papers Эндрю Кеннеди). Я считаю, что ответ на ваш последний вопрос заключается в том, что sqrt действительно является магическим в некотором смысле тем, что не должно быть возможности определить параметрическую функцию с сигнатурой этого типа с помощью обычных средств. Однако это можно делать то, что вы хотите (по крайней мере, в текущей версии F #), воспользовавшись бокса и литья:

let sqrt (x : float<'u^2>) = 
    let x' = (float x) ** 0.5 (* delete unit and calculate sqrt *) 
    ((box x') :?> float<'u>) 
6

@kvb является правильным, более общо:

Если у вас есть алгоритм, не относящийся к единицам (например, вы пишете «кубический корень»), и вы хотите разместить на нем единицы, вы можете обернуть алгоритм в функцию с правильной подписью типа и использовать, например, «плавать», чтобы «отбросить» единицы, когда они входят, и подход «снизу» и «снижать» соответствующие единицы на выходе.

В релизе RTM (после Beta2) F # будет иметь примитивные библиотечные функции для «добавочных единиц», так как подход «box-and-downcast» в настоящее время является частью взлома, чтобы преодолеть недостаток этих примитивов в язык/библиотека.

+0

Спасибо - Не могли бы вы назвать эти новые библиотечные функции (Link)? – Dario

+3

Они, вероятно, будут называться, например. «val inline FloatWithMeasure: float -> float <'u>» в модуле LanguagePrimitives. – Brian

+0

И вот он: http://msdn.microsoft.com/en-us/library/ee806527(VS.100).aspx – Benjol