F# Ununit - reunit inside a function

前端 未结 2 1207
遥遥无期
遥遥无期 2020-12-21 09:58

This question is closely related to these ones (1, 2, 3)

I\'m using an external library which doens\'t (yet) handle units of measure. I want to be able to \

2条回答
  •  無奈伤痛
    2020-12-21 10:28

    And just for fun, here is the opposite:

    let deunit (fn:float<'u> -> float<'v>) (v:float) =
        let unit = box 1. :?> float<'u>
        fn(v * unit) |> float
    

    Test :

    #light
    
    []type mm
    
    let reunit (fn:float -> float) (v:float<'u>) =
        let unit = box 1. :?> float<'u>
        unit * (fn(v/unit))
    
    let deunit (fn:float<'u> -> float<'v>) (v:float) =
        let unit = box 1. :?> float<'u>
        fn(v * unit) |> float
    
    let nounits v = v + 2.5            //function with no units
    let withunits = reunit nounits     //make it handle units (run with next line)
    withunits 2.5                  //try it -> 5.0
    
    let newnounits = deunit withunits  //remove unit handling
    newnounits 2.5                     //try it -> 5.0
    
    let withunits2 = reunit newnounits //reunit to another function
    withunits2 2.5               //try with different units
    

    Weird stuff with that #"(£$! Value restriction error in there if you run let withunits = reunit nounits on it's own. So you have to run it with the line that uses withunits. I guess it's not surprising, you have to pass in the (v:float<'u>) to reunit for F# to be able to work out what 'u is. Possibly makes reunit of limited interest, I guess...

    UPDATE: A slightly kooky workaround is to pass in 'model' values

    let reunit2 (fn:float -> float) (model:float<'u>*float<'v>) =
        let unitin = box 1. :?> float<'u>
        let unitout = box 1. :?> float <'v>
        (fun v -> (fn(v / unitin)) * unitout)
    
    let withunits3 = reunit2 nounits (0., 0.)
    withunits3 3.5
    

提交回复
热议问题