2009-01-10 25 views
6

Tôi đọc một hướng dẫn sử dụng ví dụ sau (mà tôi sẽ khái quát phần nào):Khi phá hủy bộ dữ liệu trong Haskell, các yếu tố có thể được sử dụng ở đâu?

f :: Foo -> (Int, Foo) 
... 
fList :: Foo -> [Int] 
fList foo = x : fList bar 
    where 
    (x, bar) = f foo 

Câu hỏi của tôi nằm trong thực tế rằng có vẻ như bạn có thể tham khảo xbar, theo tên, ngoài tuple nơi họ thu được. Điều này có vẻ hoạt động như danh sách tham số phá hoại bằng các ngôn ngữ khác, nếu tôi đoán là đúng. (Nói cách khác, tôi không phải làm như sau :)

fList foo = (fst tuple) : fList (snd tuple) 
     where 
     tuple = f foo 

Tôi có đúng về hành vi này không? Tôi chưa bao giờ thấy nó được đề cập trong các hướng dẫn/sách tôi đã đọc. Ai đó có thể chỉ cho tôi biết thêm thông tin về chủ đề này không?

Chỉnh sửa: Bất kỳ điều gì (danh sách, mảng, v.v ...) có bị phá hoại theo cách tương tự hay bạn chỉ có thể làm điều này với bộ dữ liệu?

+1

Nếu cuối cùng bạn không giải thích được sự khớp mẫu trong hướng dẫn đó, bạn có thể muốn bổ sung nó với lời giải thích đầy đủ hơn về Haskell. So khớp mẫu là cơ bản và quan trọng đối với ngôn ngữ. –

Trả lời

13

Thấy chỉnh sửa của bạn, tôi nghĩ rằng những gì bạn hỏi về là Pattern matching.

Và để trả lời câu hỏi của bạn: Có, bất cứ điều gì bạn có thể xây dựng, bạn cũng có thể 'deconstruct' bằng cách sử dụng các nhà xây dựng. Ví dụ, bạn có thể quen với hình thức phù hợp với mô hình:

head :: [a] -> a 
head (x:xs) = x 
head []  = error "Can't take head of empty list" 

Tuy nhiên, có nhiều nơi mà bạn có thể sử dụng mô hình kết hợp, ký hiệu có giá trị khác là:

head xs = case xs of 
       (y:ys) -> y 
       []  -> error "Can't take head of empty list" 

head xs = let (y:ys) = xs 
      in y 

head xs = y 
    where 
    (y:ys) = xs 

Lưu ý rằng hai ví dụ cuối cùng khác một chút so với lần đầu tiên vì chúng cung cấp các thông báo lỗi khác nhau khi bạn gọi chúng với một danh sách trống.


Mặc dù những ví dụ cụ thể vào danh sách, bạn có thể làm tương tự với các kiểu dữ liệu khác, như vậy:

first :: (a, b) -> a 
first tuple = x 
    where 
    (x, y) = tuple 

second :: (a, b) -> b 
second tuple = let (x, y) = tuple 
       in y 

fromJust :: Maybe a -> a 
fromJust ma = x 
    where 
    (Just x) = ma 

Một lần nữa, các chức năng cuối cùng cũng sẽ sụp đổ nếu bạn gọi nó với Nothing.

Tổng hợp; nếu bạn có thể tạo thứ gì đó bằng cách sử dụng hàm tạo (chẳng hạn như (:)[] cho danh sách hoặc (,) cho bộ dữ liệu hoặc NothingJust cho Có thể), bạn có thể sử dụng cùng các nhà xây dựng đó để thực hiện khớp mẫu theo nhiều cách khác nhau.

2

Tôi có đúng về hành vi này không?

Có. Tuy nhiên, các tên chỉ tồn tại trong khối mà bạn đã định nghĩa chúng. Trong trường hợp của bạn, điều này có nghĩa là đơn vị logic mà mệnh đề where của bạn được áp dụng cho, tức là biểu thức bên trong fList.

0

Vâng, bạn nói đúng. Các tên bị ràng buộc trong mệnh đề where được hiển thị cho khai báo đầy đủ trước mệnh đề where. Trong trường hợp của bạn, những tên đó là fbar.

(Một trong những điều khó khăn về học tập Haskell là nó không chỉ là phép nhưng phổ biến để sử dụng các biến trong mã nguồn tại các địa điểm mà trước các địa điểm nơi các biến được định nghĩa.)

Nơi để đọc thêm thông tin về các điều khoản trong số Haskell 98 Report hoặc một trong nhiều hướng dẫn chi tiết có tại số haskell.org.

1

Một cách khác để nhìn vào nó là mã như thế này

x where x = 3 

là tương đương với

let x = 3 in x 
Các vấn đề liên quan