2014-11-05 38 views
1

我對點運算符有點困惑。我有以下代碼(用於測試):哈斯克爾:爲什麼f1。 f2 xy不工作?

test :: Int -> Int -> Int 
test x y = f1 . f2 x y 
      where f1 n = n+1 
       f2 x' y' = x' * y' 

而且我想它會首先執行該結果(F2 x和y),然後F1,而是它拋出一個錯誤。任何人都可以告訴我點運算符的確切定義和什麼等於f1。 f2 x y? (當沒有點運算符時寫)

此致敬禮, Skyfe。

編輯:如果點操作產生一個完整的新功能,我想下面的代碼應該工作:

test :: Int -> Int -> Int 
test x y = f1 . f2 x 
      where f1 n = n+1 
       f2 x' y' = x' + y' 

而且該代碼返回一個錯誤。

回答

7

綴運算符總是比在Haskell功能應用的優先級低,所以這

f1 . f2 x 

解析這樣

f1 . (f2 x) 

但是,f2 x不是類型的功能(當然,它可能是,如果f2返回一個函數,但通常情況不是這樣,或者在你的問題中)。由於(。)作用於函數,所以這不起作用。

使用($),而不是

f1 $ f2 x 
+0

啊哈感謝我得到它!所以這意味着點運算符從2個函數中創建一個新函數,但爲什麼我的第二個代碼不工作? f1。 f2 x因此將被解析爲f1。 (f2 x),其中f2 x將是仍然期待一個參數的函數,其將是與f1一樣的y參數。 – user2999349 2014-11-05 01:02:59

+1

@ user2999349,在這種情況下,您需要說'test x ='而不是'test x y ='。 – luqui 2014-11-05 01:21:49

+2

@ user2999349- @luqui打敗了我,它的問題不在於你傳入的參數(。),它是類型中'test xy'類型的不匹配(應該是一個Int)和什麼'f1。 f2 x'實際上是(它是'(Int-> Int)')。你可以把'y'放在RHS中(也就是使兩邊都輸入'Int'),或者把它從LHS中刪除(也就是讓兩邊都輸入'(Int-> Int)'來使定義一致。 – jamshidh 2014-11-05 02:53:18

2

一種常見的方法是(.)($)結合:

f1 . f2 $ x 

這可以很容易地擴展到更長的建立 「管道」:

f1 . f2 . f3 . f4 $ x 

然後,如果您發現自己需要在其他地方使用相同的組合,你只需要剪切和粘貼:

fs = f1 . f2 . f3 . f4 

... fs x ... fs y 
2

(我想其他的答案拿出$過快)

正如你已經知道,

f1 . f2 x 

被解析爲

f1 . (f2 x) 

撰寫

(f1 . f2) x 

取而代之的是做它的內容:編寫f2f1然後將這個組合函數應用到x。現在

($) :: (a -> b) -> a -> b 
f $ x = f x 

看起來像是多餘的。其主要目的是,它具有最低的優先級,這樣就可以避免括號:

foo . bar . baz $ x + y * z = (foo . bar . baz) (x + y * z) 

參見:Haskell: difference between . (dot) and $ (dollar sign)