2013-07-31 27 views
7

Hãy nói rằng tôi có một danh sách các hàmChức năng trong Haskell

functions = [f, g, h] 

mỗi một với loại a -> a

Tôi cũng có một danh sách các giá trị, nói số nhưng bất cứ điều gì nên làm việc ở đây

vals = [1,2,3] 

Tôi muốn áp dụng từng chức năng trong functions cho giá trị tương ứng trong vals

bản năng đầu tiên của tôi là sử dụng một lambda và zipWith như:

zipWith (\f v -> f v) functions vals 

Nhưng thẳng thắn này trông xấu xí và không phải cái gì tôi mong đợi trong một ngôn ngữ đẹp như vậy như Haskell. Hàm ứng dụng chức năng giống như giải pháp. Có một điều như vậy? Tôi có thiếu một cái gì đó và có một giải pháp đẹp hơn cho vấn đề của tôi? Tôi thực sự đã kết thúc viết cấu trúc này cho một giải pháp Project Euler. Nó hoạt động, nhưng tôi không thích nó.

Trả lời

16
zipWith ($) f v 

$ là ứng dụng chức năng. Thực tế là nó có ưu tiên đặc biệt thấp ném người cho một vòng lặp đôi khi.

11

Lạ lùng thay,

zipWith id functions vals 

sẽ làm việc quá!

Nhưng, thực sự, zipWith ($) là cách phù hợp để viết điều này.

+0

Bất kỳ ý tưởng nào tại sao hoạt động? –

+14

@JuanPablo Bởi vì '$' thực sự chỉ là 'id', chuyên chỉ hoạt động trên các hàm (và được ưu tiên rất thấp và một ký hiệu infix). Kiểu '$', cho rằng nó áp dụng một hàm cho một đối số, phải là '(a -> b) -> a -> b'. Nhớ rằng tất cả các hàm Haskell là "thực sự" đơn nhất (hoặc tương đương với '->' liên kết ở bên phải), cùng kiểu với '(a -> b) -> (a -> b)'. Có nghĩa là nó có chức năng của bất kỳ loại nào và cho bạn một chức năng cùng loại; chỉ là một trường hợp đặc biệt của 'id :: a -> a' lấy giá trị của bất kỳ kiểu nào và cho bạn một giá trị cùng loại. – Ben

+6

Một cách khác để xem xét nó: sử dụng 'zipWith id' có nghĩa là mỗi phần tử kết quả được tính bằng' id f v', và 'id f' bằng' f' để 'id f v' bằng' f v'. – augustss

3

Đây là một tùy chọn khác có thể khiến bạn suy nghĩ một chút.

>>> import Control.Applicative 
>>> let functions = ZipList [(+1), (*2), (*10)] 
>>> let values = ZipList [1, 2, 3] 
>>> getZipList (functions <*> values) 
[2, 4, 30] 

A ZipList chỉ là một trình bao bọc xung quanh danh sách. Định nghĩa của <*> cho một số ZipList nói "zip danh sách các hàm (ở bên trái) với danh sách các đối số (ở bên phải) bằng cách áp dụng từng hàm cho một đối số lần lượt".

Điều này trái ngược với định nghĩa <*> cho danh sách thông thường, cho biết "lấy mọi cặp có thể có (hàm, đối số) từ hai danh sách này và áp dụng hàm cho đối số".