2014-04-20 12 views
6

Learn You a Haskell giải thích foldl1:foldl thực hiện với lỗi Runtime

Các foldl1 và foldr1 chức năng hoạt động giống như foldl và foldr, chỉ bạn không cần phải cung cấp cho họ với một giá trị khởi đầu rõ ràng. Họ giả định phần tử đầu tiên (hoặc cuối cùng) của danh sách là giá trị bắt đầu và sau đó bắt đầu gấp với phần tử bên cạnh. ...

Bởi vì họ phụ thuộc vào các danh sách mà họ gấp lên có ít nhất một yếu tố , họ gây ra lỗi runtime nếu gọi với danh sách trống

I figured thực hiện được, nhiều hơn hoặc ít hơn, sau đây :

foldl1' :: (a -> a -> a) -> [a] -> a 
foldl1' f ys = foldl f (head ys) (tail ys) 

Tuy nhiên, lỗi thời gian chạy tiềm năng này làm phiền tôi.

Tại sao không triển khai foldlOption theo cách sau?

foldlOption :: (a -> a -> a) -> [a] -> Maybe a 
foldlOption f [] = Nothing 
foldlOption f ys = Just (foldl f (head ys) (tail ys)) 

REPL

*Main> foldlOption (\acc elem -> if (elem > acc) then elem else acc) [] 
Nothing 

-- find max 
*Main> foldlOption (\acc elem -> if (elem > acc) then elem else acc) [1,100,2,3] 
Just 100 

EDITED

Cập nhật foldl1 's và foldlOption' s định nghĩa để sử dụng tail ys như là đối số cuối cùng để foldl, không ys mỗi Lee Duhem 's chỉnh . .

+0

Tôi nghĩ rằng định nghĩa tương đương của 'foldl1' là' foldl1 'f ys = foldl f (đầu ys) (đuôi ys) ', hoặc' foldl1' f (y: ys) = foldl fy ys'. –

+0

Cảm ơn, Lee. Tôi vừa cập nhật và liệt kê sửa đổi của bạn. –

+0

Bạn được chào đón. –

Trả lời

12

Thực sự không có lý do chính đáng nào để không làm điều này. Nhiều chức năng trong phần mở đầu của Haskell như head, tail, init và nhiều chức năng khác không thành công. Nó sẽ là đẹp hơn cho họ để lưu ý rõ ràng thất bại của họ trong các loại, nhưng đó là tiếc là không phải những gì đã xảy ra khi Prelude đã được tiêu chuẩn hóa và chúng tôi không thể thay đổi rất nhiều chức năng cốt lõi như head! Ngày nay, tôi khuyên bạn không nên sử dụng nhiều chức năng này và chọn ghép mẫu hoặc thư viện errors của Gabriel Gonzalez cung cấp các phiên bản thay thế của các chức năng một phần của prelude không đúng cách.

Ví dụ trong Control.Error.Safe

foldl1Err :: e -> (a -> a -> a) -> [a] -> Either e a 

và lỗi cũng xuất khẩu an toàn, thư viện tương tự với Maybe 's trong đó có chức năng

foldl1May :: (a -> a -> a) -> [a] -> Maybe a 

chính xác như những gì bạn muốn :)

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