2009-01-20 5 views
3

(Je suis stillbanging avec les unités de mesure en F #)F # Unités de mesure, des problèmes avec généricité

Je vais avoir un problème faisant des fonctions « génériques » qui prennent des flotteurs « tapés ».

La classe de maquettes suivante est destinée à garder un œil sur une erreur cumulative en position, basée sur un facteur 'c'. Le compilateur n'aime pas que je dise 0. < 'a> dans le corps du type ("Paramètre de type inattendu en unité de mesure littérale").

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

Une autre question connexe, je crois, toujours faire avec des fonctions 'génériques'.

Dans le code suivant, j'essaie de créer une fonction qui prendra un #seq de n'importe quel type de flottant et l'appliquera à une fonction qui n'accepte que des flottants 'vanilla'. La troisième ligne donne une erreur 'Value Restriction', et je ne vois pas d'issue. (Retrait de la # résout le problème, mais je voudrais éviter d'avoir à écrire la même chose pour les listes, seqs, tableaux, 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 

Répondre

1

Vous pouvez modifier le premier « compilateur pas comme » à

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

et le compilateur semble comme ça.

Quant à la deuxième question, je ne vois la même erreur que vous, et ce

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

compile pour moi (bien que le upcast à seq < _> est un peu ennuyeux, je ne suis pas sûr s'il y a un moyen facile de s'en débarrasser ou non).

En plus, je pense que la convention est de nom de l'u, 'paramètres unités v ... plutôt que « a, » b, ...

+0

Je vais laisser cela comme la réponse, car elle a répondu aux deux tiers de ma question. Et merci pour le rappel sur la convention de nommage. J'aurais aimé éviter les images aussi. – Benjol

0

Unités de mesure ne peuvent pas être utilisés comme paramètres de type. C'est parce qu'ils sont effacés par le compilateur lors de la compilation. Cette question est tout à fait similaire: F# Units of measure - 'lifting' values to float<something>

+0

J'ai demandé que l'un aussi, je dois être un peu lent sur l'absorption! Je suppose que cela signifie que j'ai deux options - soit je force à une unité donnée, ou je passe dans ma valeur zéro? – Benjol

+0

Je ne suis pas sûr de comprendre ce que vous entendez par ne peut pas être utilisé comme paramètres de type, 'cos cela fonctionne: let fn (a: float <'a>) (b: float <'a>) = a * b – Benjol

Questions connexes