2017-04-06 22 views
3

我試圖理解下面的一段代碼:即使參數丟失,爲什麼此功能仍能正常工作?

import Data.Char (ord) 

encodeInteger :: String -> Integer 
encodeInteger = read . concatMap ch 
    where ch c = show (ord c) 

但我不明白如何當encodeInteger被定義爲需要一個字符串的函數這可以工作,但在第二行中,函數實現時沒有該字符串參數。

此外,concatMap(根據hoogle)採用函數和列表,但僅提供功能ch

爲什麼此代碼仍然有效?這個論證是不是神奇地通過了?它與咖喱有關嗎?

編輯:爲什麼不就努力改變這樣的:

encodeInteger :: String -> Integer 
encodeInteger a = read . concatMap ch a 
    where ch c = show (ord c) 
+1

函數'甲 - >乙 - >在Haskell C'表示功能'一個 - >(B - > C)',即,如果施加到一個'A'它產生一個'乙 - > C'。 'f a b'同樣只是'(f a)b'。如此以來,'concatMap'是(簡化的)'(一 - >並[b]) - >並[a] - >並[b]','concatMap ch'是一個函數'[A] - >並[b]'。 – Ryan

+0

嗨,謝謝,這無論如何都是有道理的。但是,我不應該做我在編輯下添加的內容嗎? – user66875

+1

@ user66875您需要將整個構圖應用於參數。現在,期待'concatMap ch a'成爲一個函數('.'的第二個參數)。使用'閱讀。 concatMap ch $ a' – Lazersmoke

回答

4

基本上定義一個函數

f = g 

相同定義函數

f x = g x 

在您的具體情況下,您可以使用

encodeInteger a = (read . concatMap ch) a 

來定義你的功能。需要的括號,否則它被解析爲

encodeInteger a = (read) . (concatMap ch a) 

concatMap ch a不是一個函數,不能組成。最多你可以寫

encodeInteger a = read (concatMap ch a) 
-- or 
encodeInteger a = read $ concatMap ch a 

關於「爲什麼concatMap ch只有一個參數?」。這是一個部分應用程序,在Haskell中很常見。如果你有

f x y z = x+y+z 

你可以叫f用更少的參數,並獲得作爲結果的剩餘參數的函數。例如,f 1 2是取z並返回1+2+z的函數。

具體而言,感謝柯里裏,沒有這樣的事情作爲一個函數採取兩個或更多的參數。每個函數總是隻有一個參數。當你有一個像

foo :: Int -> Bool -> String 

一個函數,那麼foo有一個參數,一個Int。它返回一個函數,它需要一個Bool並最終返回String。您可以通過編寫

foo :: Int -> (Bool -> String) 

無論如何想象這一點,如果你看看鑽營和部分應用程序,你會發現很多的例子。

3
encodeInteger :: String -> Integer 
encodeInteger = read.concatMap (\char -> show $ ord char) 

「=」的左側(LHS)的encodeInteger是名稱;它指的是「=」右側的功能(RHS)。兩者都具有功能類型:String -> Integer。兩者都帶有一個字符列表併產生一個整數。哈斯克爾使我們能夠表達這樣的功能,平等,而不指定形式參數(被稱爲point-free風格)。

現在,讓我們來看看在RHS。 (。)運算符將兩個函數組合在一起。所構成的函數以一個字符串作爲從concatMap其輸入,併產生出來的read作爲組成函數的輸出的整數。

concatMap本身需要2個輸入,但是我們需要離開了第二個對於組成的函數,它需要一個字符串作爲其輸入。我們通過部分申請concatMap來實現這一目標,僅包括其第一個參數。

相關問題