2009-02-21 27 views
5

Tôi đang cố gắng để tìm thấy một cách để làm chức năng sau đây với foldl:Sử dụng foldl để đếm số giá trị đích thực

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

Nó chỉ đếm số giá trị mà là đúng trong một danh sách các phép toán luận. Tôi đã tự thử bản thân mình với

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

Mà thậm chí không biên dịch. Bất kỳ đề xuất?

+0

Hàm lambda của bạn (\ i -> i) được gọi là "id". Vì vậy, có thể được giảm xuống còn count = length. id bộ lọc –

Trả lời

9

Vì vậy, hãy kiểm tra các loại các chức năng liên quan đến

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 

Vì vậy cho danh sách các Bool s, b là Bool, nhưng các chức năng bạn đang sử dụng có Bool như là đối số đầu tiên, không phải là thứ hai . Giá trị tích lũy là đối số đầu tiên. Vì vậy, thay vào đó bạn có thể làm

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

Hoặc nếu bạn chỉ muốn sửa chữa để tranh luận, sử dụng chức năng ban đầu của bạn với flip

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

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

Hoặc bạn có thể gọn gàng hơn: foldl (flip ((+) . fromEnum)) 0

+0

từEnum đáng để biết, nhưng phụ thuộc vào mã hóa Bool tùy ý. Nó sẽ không làm việc (theo cách xấu - nó sẽ biên dịch và chạy, nhưng chúng tôi không chính xác) nếu Bool đã được wriiten dữ liệu Bool = True | Sai phái sinh Enum nó sẽ là sai. –

+2

dữ liệu Bool = False | Đúng là đã được thực hiện theo thứ tự đó vì một lý do;) Nó không tùy ý. Nó cũng được định nghĩa trong báo cáo http://www.haskell.org/onlinereport/basic.html, vì vậy nếu bạn làm theo cách khác, nó không còn là Haskell nữa. –

+0

Thậm chí ngắn gọn hơn: 'tổng hợp. (Bản đồ fromEnum) '- (hai người đi qua danh sách, trừ khi bạn đang làm hợp hạch) –

4

Cách thực hiện:

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

Một cách khác để làm điều đó withou t foldl:

count list = sum $ map fromEnum list 

Tín dụng cho Logan để chỉ ra fromEnum. Đã không nghe nói về điều đó trước đây.

+0

Gọn gàng. Tôi đang học Haskell (bắt đầu một tuần trước) và tốt nhất tôi có thể nghĩ ra là: danh sách đếm = foldl (+) 0 (bản đồ (\ i -> nếu tôi sau đó 1 người khác 0) danh sách) – eljenso

Các vấn đề liên quan