2014-11-20 23 views
6

Đọc "Suy nghĩ về chức năng với Haskell" Tôi bắt gặp một phần của tính toán chương trình yêu cầu map sum (map (x:) xss) được viết lại như map (x+) (map sum xss)Haskell - Cách chuyển đổi bản đồ tổng (bản đồ (x :) xss) thành bản đồ (x +) (bản đồ tổng xss)

trực giác tôi biết rằng nó có ý nghĩa ...

nếu bạn có một số danh sách mà bạn đang đi để tổng hợp nhưng, trước khi tổng hợp, với những danh sách cùng bạn cũng sẽ thêm một yếu tố 'x ', thì điều đó cũng giống như lấy danh sách tổng các danh sách gốc và thêm giá trị của x vào mỗi danh sách.

Nhưng tôi muốn biết làm thế nào để biến đổi một thành khác chỉ bằng cách sử dụng lý luận equational. Tôi cảm thấy như tôi đang thiếu luật hoặc quy tắc sẽ giúp tôi hiểu.

Trả lời

12

Sử dụng pháp luật

map f (map g list) === map (f . g) list 

Chúng ta có thể suy ra

map sum (map (x:) xss) = 
map (sum . (x:)) xss = 

eta-mở rộng để cung cấp cho một cuộc tranh cãi để làm việc với

map (\xs -> sum . (x:) $ xs) xss = 

Thay in cho (f . g) x === f (g x)

map (\xs -> sum (x:xs)) xs = 

đâu

sum (x:xs) = x + sum xs 
sum [] = 0 

nên

map (\xs -> sum (x:xs)) xss = 
map (\xs -> x + sum xs) xss = 

Thay f (g x) === (f . g) x

map (\xs -> (x +) . sum $ xs) xss = 

eta-giảm lambda

map ((x +) . sum) xss = 

Việc sử dụng đảo ngược luật đầu tiên từ trên

map (x+) (map sum xss) 
+0

Tôi không đồng ý về việc hiểu danh sách, nhưng chắc chắn là vấn đề về hương vị. Tại sao không chỉ sử dụng định nghĩa '(.)' Và nói 'map (sum. (X :)) xss = map (\ xs -> sum (x: xs)) xss = map (\ xs -> x + sum xs) = ... '? – kosmikus

+0

@kosmikus Eh, sở thích cá nhân. Trong trường hợp này nó khá là không quan trọng, nhưng tôi có thể thấy lập luận để giữ 'bản đồ' trong đó toàn bộ thời gian. – bheklilr

+0

@kosmikus trông đẹp hơn? – bheklilr

0

Tôi khuyên bạn nên xem xét các loại và cho phép chúng hướng dẫn bạn qua quá trình chuyển đổi.

> let xss = [[1], [2], [3]] 
> :t xss 
xss :: Num t => [[t]] 
> map sum xss  -- basically compacting the lists 
[1,2,3] 
> :t map sum xss -- into just a list of numbers 
map sum xss :: Num b => [b] 

Tiếp theo chúng ta cần phải làm việc bổ sung

> :t (+5) 
(+5) :: Num a => a -> a 
> :t map (+5)  -- no magic in this 
map (+5) :: Num b => [b] -> [b] 
> map (+5) (map sum xss) 
[6,7,8] 

Điểm mấu chốt Tôi đoán là trong ví dụ đầu tiên bạn đang thay đổi các loại theo cách khác hơn là trong một giây. Điểm mà một danh sách các danh sách trở thành chỉ là một danh sách thay đổi, và do đó có cách mà bạn thêm số.

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