2012-07-25 82 views
3

我有一類名爲「Person」綁定值不是第一個參數

Person :: String -> String -> Int -> Gender -> Person 

目標: 爲了人的femalePerson的更一般的版本通過向女指派性別。

什麼工作: 綁定前N個元素的作品:

let personsWithNameAlice = Person "Alice" 
let personsWithNameAliceMcGee = Person "Alice" "McGee" 

什麼不起作用:

let femalePerson = Person {gender = Female} 

問:

  • 我該怎麼辦?
  • 如何將一個值綁定到任何函數的第n個元素,其中n!= 0?

這只是我知道我可以在C++中編寫f(x,y,z)= g(x,y,z,5)和std :: bind2nd(f,8) Haskell有可能嗎?

回答

7

您可以用lambda表達式做到這一點,因爲

Person :: String -> String -> Int -> Gender -> Person 

你在綁定定義

femalePerson = \fn ln a -> Person fn ln a Female 

,或者帶參數:

femalePerson fn ln a = Person fn ln a Female 

如果你想具體綁定第二個參數,flip是你想要的功能

third = flip (/) 3 

您可以使用flip在任意位置綁定參數,但很快就變得麻煩和不可讀:

femalePerson = curry . curry $ flip (uncurry (uncurry Person)) Female 
+0

謝謝。如果Haskell允許將{paramName = value}語法用於綁定,那麼我會非常高興,但這樣做也可以。 – Alehar 2012-07-25 12:27:46

13

使用semantic editor combinators。 例如,假設你有一個函數:

foo :: Int -> String -> Bool -> Char -> Float 
foo = undefined 

我已經改變了例子,包括所有不同的類型,所以類型檢查將確保我們有我們的定義權。 我們希望以下4種專業化的,每從一個參數填充導致:

foo0 ::  String -> Bool -> Char -> Float -- 3 
foo1 :: Int ->   Bool -> Char -> Float -- "hey" 
foo2 :: Int -> String ->   Char -> Float -- True 
foo3 :: Int -> String -> Bool ->   Float -- 'x' 

第一個是容易的,直的部分應用程序:

foo0 = foo 3 

但是,讓我們把它寫在奇怪的方式(用於與他人稠度):

foo0 = ($ 3) foo 

對於其它,使用result,這對組合物的同義詞:

result :: (b -> b') -> ((a -> b) -> (a -> b')) 
result = (.) 

result的應用目的上的另一功能的「結果」給定功能(因此是從Control.Arrow直接類似於firstsecond函數)。 反覆應用則目標內的多個結果,跳過去連續令行禁止的論點,正是因爲我們需要:

foo1 = result ($ "hey") foo 
foo2 = (result.result) ($ True) foo 
foo3 = (result.result.result) ($ 'x') foo 

注意,第n個專業化使用result由具有自身n次。

相關問題