2017-07-18 71 views
1

我想只從一個字符串的大寫字母,並且有想法,看看是否在字符串中每個字母都包含在所有大寫字母的列表:如何使用列表理解作爲列表理解的條件?

capsOnly = [ x| x<- string, (x elem ['A'..'Z'])] 

問題是,顯然哈斯克爾做不承認逗號後面的部分應該是關於x的條件,並給我:

* Couldn't match expected type `(a0 -> t0 a0 -> Bool) 
           -> [Char] -> Bool' 
       with actual type `Char' 
* The function `x' is applied to two arguments, 
    but its type `Char' has none 
    In the expression: (x elem ['A' .. 'Z']) 
    In a stmt of a list comprehension: (x elem ['A' .. 'Z']) 

那麼,如何界定什麼是參數,什麼是其中x來自列表? 或者這是不可能的?

我知道,你也可以不喜歡它:

onlyCaps = [ x| x<- string, x < 'a'] 

,但我真的想知道,如果我的第一種方法是可能的,以及如何將它寫,如果它是

回答

6

的問題是不與列表理解本身。問題是x elem ['A'..'Z']沒有太大意義。

elem :: Eq a => a -> [a] -> Bool是一個函數,它將一個元素和一個列表作爲輸入,並檢查該元素是否屬於該列表。

所以你應該把它寫這樣的:

capsOnly = [ x | x <- string, elem x ['A'..'Z']] 

或者選擇使用backtics(使用符號):

capsOnly = [ x | x <- string, x `elem` ['A'..'Z']] 

然而,這是不是非常有效:它需要O(n)檢查會員資格。既然我們檢查範圍,更有效地做勢必檢查,如:

capsOnly = [ x | x <- string, x >= 'A', x <= 'Z'] 

這就要求在O(1)運行使其更快兩個比較。

我們在這裏做的是過濾。通常它是更好(更多的描述和聲明)使用filter :: (a -> Bool) -> [a] -> [a]這與isAsciiUpper :: Char -> Bool作謂語:

import Data.Char(isAsciiUpper) 

capsOnly = filter isAsciiUpper string 
+0

或'[X | x < - string,x \'elem \'['A'..'Z']]'(可能是OP試圖寫的第一個地方) – jwodder

+0

@jwodder:我想的完全一樣:) –

+0

我們確定GHC不會將'elem x''''''Z']'優化爲'x> ='A',x <='Z'' ..? – Redu