F # Единицы измерения, проблемы с общностью
(Я все еще banging с единицами измерения в F #)
У меня проблема с созданием "общих" функций, которые принимают "типизированные" поплавки.
Следующий класс mockup предназначен для учета вкладов кумулятивной ошибки в позиции, основанной на коэффициенте 'c'. Компилятор не любит, чтобы я произносил 0. < 'a > в теле типа ( "Неожидаемый тип параметра в литерале единицы измерения" ).
///Corrects cumulative error in position based on s and c
type Corrector(s_init:float<'a>) =
let deltaS ds c = sin (ds / c) //incremental error function
//mutable values
let mutable nominal_s = s_init
let mutable error_s = 0.<'a> //<-- COMPILER NO LIKE
///Set new start pos and reset error to zero
member sc.Reset(s) =
nominal_s <- s
error_s <- 0.<'a> //<-- COMPILER NO LIKE
///Pass in new pos and c to corrector, returns corrected s and current error
member sc.Next(s:float<'a>, c:float<'a>) =
let ds = s - nominal_s //distance since last request
nominal_s <- s //update nominal s
error_s <- error_s + (deltaS ds c) //calculate cumulative error
(nominal_s + error_s, error_s) //pass back tuple
Другой связанный с этим вопрос, по-моему, по-прежнему связан с "родовыми" функциями.
В следующем коде я пытаюсь сделать функцию, которая возьмет #seq любого типа float и применит ее к функции, которая принимает только 'vanilla' float. Третья строка дает ошибку Ограничение стоимости, и я не вижу никакого выхода. (Удаление # решает проблему, но я бы хотел не писать одно и то же для списков, секций, массивов и т.д.)
[<Measure>] type km //define a unit of measure
let someFloatFn x = x + 1.2 //this is a function which takes 'vanilla' floats
let MapSeqToNonUnitFunction (x:#seq<float<'a>>) = Seq.map (float >> someFloatFn) x
let testList = [ 1 .. 4 ] |> List.map float |> List.map ((*) 1.0<km>)
MapSeqToNonUnitFunction testList
Ответы
Ответ 1
Вы можете изменить первый "компилятор не нравится" на
let mutable error_s : float<'a> = 0.0<_>
и компилятор, похоже, нравится.
Что касается второго вопроса, я не вижу той же ошибки, что и вы, и этот
[<Measure>] type km
//define a unit of measure
let someFloatFn x = x + 1.2 //this is a function which takes 'vanilla' floats
let MapSeqToNonUnitFunction (x:seq<float<_>>) = Seq.map (float >> someFloatFn) x
let testList = [ 1 .. 4 ] |> List.map float |> List.map ((*) 1.0<km>)
let testList2 = testList :> seq<_>
let result = MapSeqToNonUnitFunction testList2
printfn "%A" result
компилируется для меня (хотя upcast to seq < _ > немного раздражает, я не уверен, есть ли простой способ избавиться от него или нет).
Кроме того, я думаю, что соглашение состоит в том, чтобы назвать параметры юнитов "u," v,... а не "a", "b",...
Ответ 2
Единицы измерения не могут использоваться в качестве параметров типа. Это происходит потому, что во время компиляции стираются компилятором. Этот вопрос очень похож:
F # Единицы измерения - значения "подъема" для float <something>