2013-09-23 58 views
3

有代碼:如何F#的管道運營商工作

//e = 1/2*Sum((yi -di)^2) 
    let error y d = 
     let map = 
      Array.map2 (fun y d -> (y - d) ** 2.0) y d 
     let sum = 
      Array.sum map 
     (sum/2.0) 

    let error2 y d = 
     Array.map2 (fun y d -> (y - d) ** 2.0) y d 
     |> Array.sum 
     |> (/) 2.0 

我瞭解這些功能應該產生相同的結果,但也有在結果相差很大。任何人都可以解釋嗎?

p.s.簡化的例子:

let test = [|1..10|] 
    let res = test 
       |> Array.sum 
       |> (/) 5 

我期望測試= 11(總和(1..10)= 55,然後55/5),但之後Array.sum管道不工作,因爲我想(如測試結果= 0) 。

回答

1

/操作員無法按照您的設想工作。你只需要更明確一點,並將error2中的最後一行更改爲

fun t -> t/2.0 

然後它應該都可以工作。

答案是因爲4是在這裏的贈品。

編輯:瞭解與/這裏所發生時需要考慮擴大了|>

下面會發生什麼都是等價的

a |> (/) b 
((/) b) a //by removing |> 
a/b  //what happens when/is reinterpreted as a function 
+0

你能解釋一下在這種情況下如何工作(/)操作符? –

+0

@DmitryMartovoi - 請參閱編輯 –

+0

你想說它會被解釋爲'b/a'而不是'a/b'嗎? –

4

你似乎誤會中綴函數的參數順序。

可以展開自由點的形式如下:

x |> (/) 5 
<=> (/) 5 x 
<=> 5/x 

所以這是你所期望的相反。它僅適用於交換功能,如(+)(*)等,如果你是熱衷於自由點式的正常工作,該flip功能有助於與|>使用:

let inline flip f x y = f y x 

let error2 y d = 
    Array.map2 (fun y d -> (y - d) ** 2.0) y d 
    |> Array.sum 
    |> flip (/) 2.0 
5

另一種選擇是使用反向

let error2 y d = 
    Array.map2 (fun y d -> (y - d) ** 2.0) y d 
    |> Array.sum 
    |> (/) <| 2.0 

編輯:|管道運營商(<)的(/),以便局部應用在正確的順序進行的參數看,如果這有助於澄清

x/y = (/) x y = y |> (/) x = x |> (/) <| y 

所有這些都是等效的。管道運營商定義爲:

(|>) x f = f x 
(<|) f x = f x 

其中f是函數,x是某個值。反向管看起來並不像它那麼多,但它可以幫助在某些情況下清理一些代碼。