2010-05-14 55 views
14

我嘗試在Haskell中開發一個簡單的平均函數。 這似乎工作:Haskell點運算符

lst = [1, 3] 

x = fromIntegral (sum lst) 
y = fromIntegral(length lst) 

z = x/y 

但爲什麼不以下版本的工作?

lst = [1, 3] 

x = fromIntegral.sum lst 
y = fromIntegral.length lst 

z = x/y 
+1

既然你計算平均值,請閱讀http://stackoverflow.com/questions/2376981/haskell-types-frustrating-a-simple-average-function/2380437 #2380437。 – kennytm 2010-05-14 14:01:27

回答

16

對於運營商而言,你會被哈斯克爾的優先規則絆倒,這很容易混淆。

當你寫

x = fromIntegral.sum lst 

哈斯克爾認爲,由於相同:

x = fromIntegral.(sum lst) 

你的意思寫的是:

x = (fromIntegral.sum) lst 
+8

的確如此。但是我認爲在他們周圍編寫沒有空格的操作符有時會導致誤解(即,看起來很像在許多以OOP爲中心的語言中構建成員訪問)。 '(從積分總和)'可能會引起問題,但不會誤解。 – ony 2010-05-14 15:50:31

+1

說實話,這裏引起混淆的不是Haskell的優先規則本身(這很容易說明),而是令人眼花繚亂的(對於初學者)數組運算符,每個運算符都有自己的優先級,在Prelude中定義。 – sigfpe 2010-05-14 20:22:33

17
.

(組合物)具有比功能應用較低的優先級,所以

fromIntegral.sum lst 

被解釋爲

fromIntegral . (sum lst) 

這是錯誤的,因爲sum lst是不是一個函數。

10

我只是想補充「$ to rescue!「:

x = fromIntegral $ sum lst 
y = fromIntegral $ length lst 

它具有最低的優先級,它避免了太多的括號級別。請注意,與(。)不同,它不執行函數組合,它將向右評估參數並將其傳遞給左側的函數。類型說明了一切:

($) :: (a -> b) -> a -> b 
(.) :: (b -> c) -> (a -> b) -> a -> c 
+1

你也可以寫'x = fromIntegral。總和$ lst',這更接近OP最初嘗試的。 – yatima2975 2010-05-14 14:41:25

+0

說它評估右邊的論點並不十分準確。評估仍然是懶惰的。爲了評估論證,你需要'$!'來代替。 – Chuck 2010-05-14 17:48:37

+0

雖然這個解決方案有效,但我不認爲這是正確的答案。對我來說,OP似乎對運營商優先權感到困惑。那麼答案就是指出正確的優先順序,並指出括號在這裏有幫助。不要再引入另一個運營商。 – Martijn 2010-05-15 07:44:26