F# 测量单位,通用性问题

发布于 2024-07-11 19:42:34 字数 1903 浏览 9 评论 0原文

仍然 使用 F# 中的测量单位)

在制作采用“类型”浮点数的“通用”函数时遇到问题。

以下模型类旨在根据因子“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 并将其应用于仅接受“普通”浮点数的函数。 第三行给出“值限制”错误,我看不到任何出路。 (删除 # 可以解决问题,但我想避免为列表、序列、数组等编写相同的内容。)

[<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

(I'm still banging on with units of measure in F#)

I'm having a problem making 'generic' functions which take 'typed' floats.

The following mockup class is intended to keep tabs on a cumulative error in position, based on a factor 'c'. The compiler doesn't like me saying 0.<'a> in the body of the type ("Unexpected type parameter in unit-of-measure literal").

///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

Another related question, I believe, still to do with 'generic' functions.

In the following code, what I am trying to do is make a function which will take a #seq of any type of floats and apply it to a function which only accepts 'vanilla' floats. The third line gives a 'Value Restriction' error, and I can't see any way out. (Removing the # solves the problem, but I'd like to avoid having to write the same thing for lists, seqs, arrays etc.)

[<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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮萍、无处依 2024-07-18 19:42:34

您可以将第一个“编译器不喜欢”更改为

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

对我来说是编译的(尽管向上转换为 seq<_> 有点烦人,我不确定是否有一个简单的方法来摆脱它或不)。

除此之外,我认为惯例是将单位参数命名为“u、”v、...,而不是“a、”b、...

You can change the first 'compiler no like' to

let mutable error_s : float<'a> = 0.0<_>

and the compiler seems to like that.

As for the second question, I am not seeing the same error as you, and this

[<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

compiles for me (though the upcast to seq<_> is a little annoying, I am not sure if there is an easy way to get rid of it or not).

Aside, I think convention is to name units parameters 'u, 'v, ... rather than 'a, 'b, ...

日暮斜阳 2024-07-18 19:42:34

测量单位不能用作类型参数。 这是因为它们在编译期间被编译器擦除。 这个问题非常相似:
F# 测量单位 - “提升”值以浮动

Units of measure cannot be used as type parameters. This is because the are erased by the compiler during compilation. This question is quite similar:
F# Units of measure - 'lifting' values to float<something>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文