1

型制約に関する Microsoftの公式ドキュメントを何度も読みましたが、このコードがコンパイルされない理由がわかりません。

let inline transform<'A, 'a when 'A : (member Item : int -> float)> (a: 'A) : 'a =
    a.[0]

エラー FS0752: 演算子 'expr.[idx]' は、このプログラム ポイントより前の情報に基づく不定型のオブジェクトで使用されています。さらにタイプ制約を追加することを検討してください

そして:

let inline transform<'A, 'a when 'A : (member f : int -> float)> (a: 'A) : 'a =
    a.f(0)

エラー FS0072: このプログラム ポイントより前の情報に基づいて、不確定な型のオブジェクトを検索します。オブジェクトの型を制約するために、このプログラム ポイントの前に型注釈が必要になる場合があります。これにより、ルックアップを解決できる場合があります。

明らかに、f# のジェネリックでメンバー制約を使用する方法がわかりませんでした。float[]私が直面している一般的な問題は、 standard のような「ベクトルのような」型、またはDiffSharpパッケージから、またはそれVector<float>からMathNet.Numericsでも汎用関数を作成したいということです 。現在、 (full code) のように、各タイプのアドホック関数を取得する必要があります。DV

#I ".paket/load"
#load "mathnet.numerics.fsharp.fsx"
#load "diffsharp.fsx"

open DiffSharp.AD.Float64

open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.LinearAlgebra.Double

let l1 = 4.5
let l2 = 2.5

let a0 = [1.1; -0.9]

let inline transformVec (a:Vector<float>) =
    let x1, y1 = l1 * cos a.[0], l1 * sin a.[0]
    let x2, y2 = x1 + l2 * cos (a.[0] + a.[1]), y1 + l2 * sin (a.[0] + a.[1])
    vector [x1; y1; x2; y2]

let inline transformDV (a:DV) =
    let x1, y1 = l1 * cos a.[0], l1 * sin a.[0]
    let x2, y2 = x1 + l2 * cos (a.[0] + a.[1]), y1 + l2 * sin (a.[0] + a.[1])
    toDV [x1; y1; x2; y2]

ご覧のとおり、この関数はまったく同じことを行いますが、異なる型で動作します。

(動作しないコード) のような一般的な関数を取得したい:

let inline transform<'A, 'a when 'A : (member Item : int -> 'a)> (toExt : 'a list -> 'A) (a: 'A) : 'A =
    let x1, y1 = l1 * cos a.[0], l1 * sin a.[0]
    let x2, y2 = x1 + l2 * cos (a.[0] + a.[1]), y1 + l2 * sin (a.[0] + a.[1])
    toExt [x1; y1; x2; y2]

let transformVec = transform vector
let transformDV = transform toDV  

私は何が欠けていますか?


編集:私は半分働いていますMathnet.Numerics

let inline transform (toExt : 'a list -> 'A) (a: 'A) : 'A = 
    let inline get i : 'a = (^A : (member get_Item: int -> 'a) a,i)
    let x1, y1 = l1 * cos (get(0)), l1 * sin (get(0))
    let x2, y2 = x1 + l2 * cos (get(0) + get(1)), y1 + l2 * sin (get(0) + get(1))
    toExt [x1; y1; x2; y2]

(transform vector) (vector a0)

'aそれは(警告 FS0064)を強制するためfloat、私は望んでいません...(DVfromDiffSharp戻り値Dタイプ on get_Item、ではありませんfloat。)

宣言を次のように置き換えます

let inline transform<'a> (toExt : 'a list -> 'A) (a: 'A) : 'A = 

コンパイラを鳴らします:

エラー FS0001: コンパイル時に型パラメーターを解決できないため、宣言された型パラメーター 'a' はここでは使用できません

4

1 に答える 1