2009-02-21 11 views
5

ich einen Weg zu finden, ich versucht, die folgende Funktion mit foldl zu tun:foldl Mit Anzahl der wahren Werte zählen

count a = length (filter (\i -> i) a) 

Es zählt nur die Anzahl der Werte, die in einer Liste von booleans wahr sind. Ich habe es selbst mit

count = foldl (\i -> 
      case i of 
       True -> (1+) 
       False -> (0+) 
      ) 0 

versucht, die nicht einmal kompilieren. Irgendwelche Vorschläge?

+0

Ihre Lambda-Funktion (\ i -> i) heißt "id". Also könnte das auf count = length reduziert werden. Filter-ID –

Antwort

9

also lasst uns die Typen der Funktionen

Prelude> :t (\i -> case i of { True -> (1+) ; False -> (0+) }) 
(\i -> case i of { True -> (1+) ; False -> (0+) }) :: (Num t) => Bool -> t -> t 
Prelude> :t foldl 
foldl :: (a -> b -> a) -> a -> [b] -> a 

Also für Ihre Liste der Bool s beteiligt überprüfen, b ist Bool, aber die Funktion, die Sie hat Bool als erstes Argument verwendet wird, nicht die zweite . Der akkumulierte Wert ist das erste Argument. Anstatt also könnten Sie

foldl (\acc p -> case p of { True -> acc + 1 ; False -> acc }) 0 

tun oder wenn Sie nur möchten, dass das Argument, um zu beheben, verwenden Sie Ihre ursprüngliche Funktion mit flip

Prelude> :t flip 
flip :: (a -> b -> c) -> b -> a -> c 

foldl (flip (\i -> case i of 
          True -> (1+) 
          False -> (0+) 
      )) 0 

Oder Sie können prägnanter sein: foldl (flip ((+) . fromEnum)) 0

+0

Das fromEnum ist wissenswert, hängt aber von einem etwas willkürlich kodierten Bool ab. Es würde nicht funktionieren (auf die schlechte Art - es würde kompilieren und ausführen, aber wir sind falsch), wenn Bool Daten geschrieben worden wäre Bool = True | Falsche Ableitung Enum es wäre falsch. –

+2

Daten Bool = Falsch | Wahr wurde in dieser Reihenfolge aus einem Grund getan;) Es ist nicht willkürlich. Es ist auch in dem Bericht http://www.haskell.org/onlinereport/basic.html definiert. Wenn Sie es also anders machen, ist es nicht mehr Haskell. –

+0

Noch prägnanter: 'Summe. (map fromEnum) '- (zwei Durchläufe durch die Liste, außer du machst Fusion) –

4

Wie wäre es mit:

count = foldl (\i v -> if v then i + 1 else i) 0 

Eine andere Möglichkeit, es ohne zu tun t foldl:

count list = sum $ map fromEnum list 

Credit Logan für fromEnum Hinweis. Ich hatte noch nie davon gehört.

+0

Ordentlich. Ich lerne Haskell (begann vor einer Woche) und das Beste, was ich mir vorstellen konnte, war: count list = foldl (+) 0 (map (\ i -> wenn ich dann 1 else 0) liste) – eljenso