2009-02-13 35 views
7

Tôi là người mới sử dụng Haskell, mặc dù đã có trải nghiệm Lisp/Scheme trước đó. Ngay bây giờ tôi đang xem xét các ví dụ từ SICP và cố gắng triển khai chúng trong Haskell để có được nhiều kinh nghiệm thực hành hơn. Trong bài giảng 3b tác giả trình bày một chức năng để tính toán các dẫn xuất tượng trưng. Nó chứa, trong số những người khác, những dòng sau:Kiểm tra nội bộ của các chức năng trong Haskell

(define (deriv exp var) 
    (cond ((constant? exp var) 0) 
      ((same-var? exp var) 1) 
; ... 

Tiếp tục trong bài giảng, một số chức năng hơn được định nghĩa:

(define (constant? exp var) 
    (and (atom? exp) 
     (not (eq? exp var)))) 

Có cách nào để làm điều tương tự trong Haskell, tức là kiểm tra số nguyên tử và tương đương tượng trưng cho một số chức năng khác? Hoặc tổng quát hơn, các phương tiện "tháo rời" chức năng trong Haskell là gì?

Trả lời

4

Ví dụ về Đề án của bạn không thực sự kiểm tra các hàm Đề án. Gần đây tôi đã làm một số sự khác biệt mang tính biểu tượng trong Haskell hơn giá trị của các loại sau đây:

data Exp a = Lit a 
      | Exp a :*: Exp a 
      | Exp a :+: Exp a 
      | Var String 
    deriving Eq 

Thay vì phân biệt đối xử bằng atom? hoặc eq? bạn sử dụng case (hoặc các mô hình phù hợp) và ==.

+0

Điều gì về việc đánh giá dữ liệu Exp của bạn (theo như tôi hiểu, đây là danh sách cuối cùng)? –

+0

Tôi thực sự không cần một hàm eval; Tôi đã sử dụng sự khác biệt tượng trưng để phát ra mã C. Nếu bạn muốn viết một và gặp rắc rối, hãy đăng câu hỏi :-) –

1

Tôi không nghĩ bạn có thể làm điều đó. Lisp là homoiconic, Haskell thì không.

Tuy nhiên, thêm Googling bật lên Liskell, đó là (?) Một kết hợp thú vị.

+1

Vâng, tôi mặc dù về tính đồng nhất. Tuy nhiên, tôi không cần các hàm, dữ liệu và chính chương trình được biểu diễn theo cùng một cách. Thực tế là đại diện của các loại dữ liệu đại số khác với một trong những chương trình không giới hạn tôi trong việc giải mã chúng. –

6

Thứ nhất, mặc dù SICP là rất tốt, tôi khuyên bạn nên chống lại nó để học Haskell. (#) Một số khó khăn trong câu hỏi này bắt nguồn từ điều này.

Trong Lisp/Scheme, một 'function' được coi là một đoạn mã và kiểm tra hàm chỉ đơn giản là kiểm tra mã của nó. Trong Haskell, một 'function' có nghĩa là một cái gì đó gần với định nghĩa toán học của nó, như một bản đồ từ tập A đến tập B. Vì vậy, ví dụ, nó có ý nghĩa, trong ngữ cảnh Lisp, để so sánh hai hàm: chỉ cần so sánh mã của chúng. (Nhưng là (x+y)^2x^2+2*x*y+y^2 các chức năng khác nhau?) Trong Haskell, nó phụ thuộc vào việc liệu có tồn tại một quy trình xây dựng để xác định sự bình đẳng cho lớp chức năng mà bạn đang xem xét hay không. Tương tự, như trong câu hỏi của bạn, trong Lisp/Scheme, bạn sẽ viết một hàm "lấy được" để phân biệt chính xác khi các biểu thức đã cho, và chỉ lỗi hoặc trả về rác trên các đầu vào tùy ý. Theo hệ thống kiểu của Haskell, đây là (AFAIK) không thể làm được, bởi vì - nếu bạn nghĩ về nó - không có điều gì khác biệt với đầu vào tùy ý: bạn chỉ có thể phân biệt Biểu thức (hoặc có thể là một lớp tổng quát hơn, nhưng vẫn không mọi điều). Vì vậy, như trong câu trả lời Norman Ramsey, trước tiên bạn xác định một "Biểu hiện" loại (hoặc kiểu lớp), mà là rất đơn giản để làm, và sau đó viết các chức năng

derive :: Expression -> Expression 

rằng disassembles một Expression sử dụng các cấu trúc mô hình khớp (hoặc một cái gì đó khác tùy thuộc vào cách Expression s được xây dựng).


(#): Lý do là SICP có triết lý hoàn toàn khác, liên quan đến việc sử dụng ngôn ngữ lập trình chưa được phân loại và khuyến khích thiếu sự phân biệt giữa mã và dữ liệu. Mặc dù có một số thành tích đối với đối số "code = data" (ví dụ: trên kiến ​​trúc von Neumann mà chúng tôi sử dụng, "mọi thứ đều là 0 và 1s"), nó không nhất thiết là cách lý giải hoặc mô hình hóa các vấn đề.(Xem số Why Calculating is Better than Scheming của Philip Wadler để biết thêm về điều này.) Nếu bạn muốn đọc một cuốn sách Haskell với một hương vị chức năng thay vì Real World, có lẽ là Haskell: The Craft of Functional Programming của Simon Thompson hoặc Introduction to Functional Programming using Haskell của Richard Bird là lựa chọn tốt hơn.

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