2016-09-11 16 views
12

tôi đang tìm kiếm tại một số mã nguồn Haskell và đã xem qua một mô hình phù hợp với !_, mã là ở đây: http://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.List.html#unsafeTakeKhi là nó hữu ích để sử dụng "wildcard nghiêm ngặt" trong Haskell, và nó làm gì?

take n xs | 0 < n  = unsafeTake n xs 
      | otherwise = [] 

-- A version of take that takes the whole list if it's given an argument less 
-- than 1. 
{-# NOINLINE [1] unsafeTake #-} 
unsafeTake :: Int -> [a] -> [a] 
unsafeTake !_ []  = [] 
unsafeTake 1 (x: _) = [x] 
unsafeTake m (x:xs) = x : unsafeTake (m - 1) xs 

Tôi không thực sự hiểu thế nào là "ký tự đại diện nghiêm ngặt" hoạt động và tại sao nó rất hữu ích để chức năng này (hoặc bất kỳ chức năng nào khác).

Trả lời

12

Ý tưởng là unsafeTake (và take cho rằng vấn đề), khi được hỏi để trả lại m yếu tố đầu tiên của danh sách trống, nó sẽ trả về danh sách trống rỗng, không có vấn đề gì giá trị của m là. Nhưng điều gì sẽ xảy ra nếu m là một biểu thức ném một ngoại lệ? Ví dụ, nó sẽ là kỳ lạ cho unsafeTake undefined [] trở []. Vì vậy, chúng ta cần phải đảm bảo rằng m đánh giá để nguyên ngay cả khi chúng ta không quan tâm đến giá trị chính xác của nó là gì (đối với trường hợp danh sách trống dĩ nhiên). Điều này làm cho unsafeTake hành xử theo cách tương tự khi nói đến đối số đầu tiên của nó, không quan trọng cho dù đối số thứ hai (danh sách) là rỗng hay không.

+1

Tôi cho rằng nó đáng nói rằng nếu bạn sử dụng 'take' chức năng với' undefined' là 'luận n' thì nó khó có khả năng bắt lỗi trong' chức năng unsafeTake' vì 'n' được so sánh với số không trước đó, tức là nó sẽ được đánh giá trước đó. Nhưng vì hàm 'take' được cho là được gạch chân càng nhiều càng tốt (như bình luận nói) thì kiểm tra này có thể biến mất sau khi một số tối ưu hóa. Đó là lý do tại sao chúng ta cần '! _' trong' unsafeTake'. – Shersh

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