1

u=(u1, u2, ..., un) および v=(v1, v2, ..., vn) を使用し、u1*v1 + u2*v2 を出力するカリー化された関数「multvec」を作成しようとしています。 + ... + un*vn. 私はロジックがほとんど正しいと思います(少なくとも他の言語ではそうです...)が、私は次のことを続けています:

stdin(11,57): error FS0001: This expression was expected to have type
'a list    
but here has type
'c list * 'd list -> 'b list

コードは次のとおりです。問題は明らかに最後の行の product への呼び出しにあります。ただし、基本ケース ( x * y )::[ ] は、実際に生成するものではなく、単に 'a リストを生成するという印象を受けました。

let rec multvec xs ys = function
    | [ ], [ ] -> failwith "Both lists cannot be empty"
    | x::[ ], y::[ ] -> ( x * y )::[ ]
    | x::xs, y::ys -> let product = multvec xs ys
                      ( x * y ) + ( List.reduce (+) product )

このエラーを明確にしていただければ幸いです。前もって感謝します。

4

2 に答える 2

8

あなたのコードは正直なところ、正しいよりも間違っています: ;-]

  • 末尾再帰ではありません
  • functionwhenxsysare 別のパラメータの使用
  • 不完全なパターン マッチ
  • 1 つの分岐をリストに評価し、別の分岐をスカラーに評価する
  • すべての製品は手動で一緒に追加されますが、最後のものはList.reduce単一要素のリストにまたがっています – 少し後ろ向きです ;-]

上記のすべてを修正する賢明な実装を次に示します。

let inline multvec xs ys = List.map2 (*) xs ys |> List.sum

List.sumパフォーマンスが主な関心事である場合は、チェックされた算術演算を使用するため、避ける価値があることに注意してください。チェックされていない算術演算を使用しても問題ない場合は、代わりに次のようにすることができます。

let inline multvec xs ys = List.map2 (*) xs ys |> List.reduce (+)

これを手動で行いたい場合は、次の 1 つの方法があります。

let inline multvec xs ys =
    let rec impl acc = function
        | [], []         -> acc
        | x::xs', y::ys' -> impl (x * y + acc) (xs', ys')
        | _              -> failwith "lists must be of equal length" 
    impl LanguagePrimitives.GenericZero (xs, ys)
于 2013-03-02T05:16:58.280 に答える
1

ildjarn の回答に追加するには、2 つのベクトルの内積 ("multvec") を計算するために使用して、 map2andreduceを単一の関数呼び出しに融合できます。fold2

let inline dot xs ys =
    let zero = LanguagePrimitives.GenericZero
    List.fold2 (fun acc x y -> acc + x * y) zero xs ys

これにより、不要な一時リストを作成する必要がなくなります。

于 2013-03-05T10:14:03.573 に答える