2

この問題は以前にも現れており、その理由は John Palmer によって回答され ています。

let ar = Array.zeroCreate<int> (64*1024*1024)
#time
//Real: 00:00:00.171, CPU: 00:00:00.171, GC gen0: 0, gen1: 0, gen2: 0
for i in 0 .. ar.Length - 1 do
    ar.[i] <- ar.[i]*3

//Real: 00:00:00.327, CPU: 00:00:00.328, GC gen0: 0, gen1: 0, gen2: 0
ar |> Array.iteri(fun i _ -> ar.[i] <- ar.[i]*3)

//Real: 00:00:02.249, CPU: 00:00:02.250, GC gen0: 0, gen1: 0, gen2: 0
ar |> Seq.iteri(fun i _ -> ar.[i] <- ar.[i]*3)

これらの動作を加速するために、シーケンスを(最後に知られている?)具象型にマッピングできる、ある種の「インライン化」またはその他の一般的なメカニズムがあるかどうか疑問に思います。たとえば、ここでは、配列を反復処理するという静的な保証があります。

これに対して理論的に存在する満足のいく解決策を知っていますか? (派手な名前は何ですか?)

その問題をうまく認識して解決する言語はありますか?

4

3 に答える 3

4

F# に高次の種類の型がないことは事実ですが、インライン関数を使用して Typeclass の動作をエミュレートすることはできます。Functor を定義することで、ネイティブ マッピングに対する一般的な解決策が得られます。

type Fmap = Fmap with
    static member ($) (_Functor:Fmap, x:List<_> ) = fun f -> List.map    f x  
    static member ($) (_Functor:Fmap, x:array<_>) = fun f -> Array.map   f x
    static member ($) (_Functor:Fmap, x:_ [,]   ) = fun f -> Array2D.map f x
    static member ($) (_Functor:Fmap, x:_ [,,]  ) = fun f -> Array3D.map f x
    static member ($) (_Functor:Fmap, x:_ [,,,] ) = fun f ->
        Array4D.init (x.GetLength 0) (x.GetLength 1) (x.GetLength 2) (x.GetLength 3) (fun a b c d -> f x.[a,b,c,d])

let inline fmap f x = (Fmap $ x) f

fmap を例にとると、この関数はインラインであり、オーバーロードで定義された任意の型を受け入れ、関数を直接呼び出すのと同じくらい速く実行されます (これは実際に舞台裏で行われます)。反復するには、fmap を使用して結果を破棄できます。この場合、fmapi のようなものを定義して、インデックスを利用できるようにすることができます。

これらの関数は常に具象型で呼び出す必要があることに注意してください。Seq<'a> を渡すと失敗します。サブタイプとアドホック ポリモーフィズムの両方のアプローチを混在させないでください。

于 2012-11-29T10:11:52.550 に答える
2

これに対して理論的に存在する満足のいく解決策を知っていますか? (派手な名前は何ですか?)

ケーキを持って食べることはできません。

その問題をうまく認識して解決する言語はありますか?

F# はこの問題を認識し、うまく解決しました。明確なパフォーマンス プロファイルと F# のような高速コンパイルを使用することも、このような特殊なケース向けの最適化パスを搭載した非常に複雑なコンパイラのために、予測不可能なパフォーマンス プロファイルと低速コンパイルを使用することもできます。F# は前者の (実用的な) ソリューションを選択しました。

于 2012-11-30T05:41:40.793 に答える
0

コレクションのタイプをチェックして、iter最適な実装にディスパッチできます。問題が発生するのは で、いくつかのmapを返す必要があります。これには、F# が直接サポートしていない上位の種類の型が必要です。問題を説明する試みは次のとおりです。T<'b>T<'a>map

module AnySeq =
  let map<'a, 'b, 'c, 'd when 'a :> seq<'b> and 'd :> seq<'c>> (f: 'b -> 'c) (s: 'a) : 'd =
    let (!) x = unbox (box x)
    let tyDef = s.GetType().GetGenericTypeDefinition()
    if tyDef = typedefof<list<_>> then !(List.map f !s)
    elif tyDef = typedefof<array<_>> then !(Array.map f !s)
    else !(Seq.map f !s)

それを使用して を に変換しようとするint listfloat list:

let ints = List.init 10000000 id
let floats = ints |> AnySeq.map float

値制限エラーが発生します。

値 'floats' はジェネリック型 val floats を持つと推測されています: '_a when '_a :> seq

に型注釈を追加すると機能しfloatsますが、何も達成していません。

于 2012-11-28T17:02:23.517 に答える