2012-02-06 96 views
2

假設我們需要列表x的那些元素,其中列表y的對應元素嚴格爲正。以下任何工作的三項解決方案:列表的布爾選擇

let x = [1..4] 
let y = [1, -1, 2, -2] 

[ snd both | both <- zip (map (> 0) y) x, fst both ] 

map snd $ filter fst $ zip (map (>0) y) x 

sel :: [Bool] -> [a] -> [a] 
sel [] _ = [] 
sel (True : xs) (y : ys) = y : sel xs ys 
sel (False : xs) (y : ys) = sel xs ys 

sel (map (> 0) y) x 

然而,是什麼促使這是在R語言這個可以緊湊這樣寫的:

x[y > 0] 

並給出了多少,我想知道是否有一個更短/更好的方式在Haskell做到這一點?

回答

1

如果你願意使用語言的擴展,我可以提供在Haskell替代

{-# LANGUAGE ParallelListComp #-} 

bfilter :: (b -> Bool) -> [a] -> [b] -> [a] 
bfilter cond xs ys = [x | x <- xs | y <- ys, cond y] 

沒有將接近儘可能短,將R版本,因爲在R,它內置了語言,但在Haskell中卻不是。顯然,設計R的人發現這裏有一個很好的理由來包含這樣一個原始的,但沒有一個Haskell設計師發現那裏有令人信服的理由將這樣一個構造包含在語言中(並且它不會很好地適應,所以我完全支持這個決定 - 它可能適合R,我不知道那種語言)。

+0

關於您關於內置其不僅僅是R的聲明,而且還在關係數據庫中將選擇視爲基礎的說法。例如,在SQL中,我們有'從mytable中選擇x,其中y> 0'。 – user1189687 2012-02-06 12:56:14

+0

這是一回事嗎?據我瞭解,我們有兩個不相關的 - 除了它們都有列表(R中的數組) - 實體並根據相應索引的另一個元素的條件從一個條目中選擇條目(順便說一句,怎麼做如果'x'和'y'具有不同的長度,則R表現如何?與Haskell相同,在較短的運行時錯誤結束時停止?)。如果'y'不是'mytable'的一部分,那麼'從x表中選擇x從y> 0是甚至可能的嗎? – 2012-02-06 13:10:10

+0

我認爲我們可以假定可比性(相同長度,同一個表格等)的必要條件。問題的癥結在於更容易進行選擇。 – user1189687 2012-02-06 13:42:30

1
zip x y >>= \(a,b) -> filter(const(b>0)) [a] 

或者白白使用應用型...

import Control.Applicative 

zip x y >>= filter <$> const.(>0).snd <*> (:[]).fst 
1

丹尼爾·菲捨爾說,沒有這方面的任何特殊語法。

如果你經常要做這個操作,最好是定義你自己的單個可重用函數,而不是每次手動組裝列表理解或映射/過濾器鏈。 (因爲調用方具有單獨申請的mapsel不通過這項測試。)

所以

selectWhere :: [a] -> (a -> Bool) -> [b] -> [b] 
selectWhere ys pred = map snd . filter (pred . fst) . zip ys 
-- call it like this: selectWhere y (> 0) x 

,或者你喜歡的任何明確的定義。重要的是你把它包裝在一個函數中。