2011-11-19 33 views
7

tôi phải mất mã này:Tái sử dụng một hàm Lambda trong Haskell

f x y z = x^3 - g (x + g (y - g z) + g (z^2)) 
where g x = 2*x^2 + 10*x + 1 

Và viết lại nó mà không nơi (hoặc để).

Họ có nghĩa là để viết nó với một chức năng Lambda (\ x -> ...)

Tôi đang cố gắng để tái sử dụng một hàm Lambda trên Haskell. Bất kỳ ý tưởng?

+6

'f = lật lật ((1 +) ap ((+). (2 *). (^ 2)) (10 *)). (lật.) ap ((.). (.). (.). (-). (^ 3)) (((ap id.).). lật lật (lật id. (^ 2)). (liftM2 (liftM2 (() (.) (. – fuz

Trả lời

12

Như gợi ý bravit tại, bạn có thể viết lại một tổ chức phi đệ quy let sử dụng một lambda theo cách sau:

let x = A in B  ==>  (\x -> B) A 

nơi x là biến và AB là các biểu thức.

+5

Điều tôi thấy buồn cười về mẹo này là nó thực sự là một thực hành tiêu chuẩn trong Javascript vì chỉ có các hàm mới có thể giới thiệu một khối phạm vi ở đó. – hugomg

+1

Tôi vẫn không chắc mình hiểu cách có thể sử dụng lại nó – Asaf

+0

@Asaf: Bạn có thể tham chiếu đến 'x' nhiều lần trong' B'. Ví dụ, lấy '(\ x -> x + x) 3'. Điều này tương đương với '3 + 3', ngoại trừ bạn chỉ phải viết' 3' một lần. – hammar

8

Để sử dụng lại thứ gì đó bạn có thể biến nó thành một cuộc tranh luận về điều gì đó.

2

Tôi nghĩ rằng ý định là những gì gợi ý gợi ý.
Các thông thái theo-the-chữ-of-the-luật workaround được ràng buộc g với một case;)

+2

Một giải pháp thông minh khác sẽ làm cho 'g' trở thành một chức năng cấp cao nhất, vì nó không đóng bất cứ thứ gì từ' f' :) – hammar

2

Để mở rộng gợi ý của hammar và bravit, giải pháp của bạn sẽ yêu cầu không chỉ một lambda, nhưng hai - một trong số đó sẽ trông rất tuyệt như g, và một trong số đó sẽ trông rất giống thứ hai một nửa số f

1

Sử dụng phép tính lambda g(\x -> 2*x^2 + 10*x + 1)

Vì vậy, bạn cần phải thay thế g với điều đó trong f x y z = x^3 - g (x + g (y - g z) + g (z^2))

$> echo "f x y z = x^3 - g (x + g (y - g z) + g (z^2))" | sed -r -e 's/g/(\\x -> 2*x^2 + 10*x + 1)/g' 
f x y z = x^3 - (\x -> 2*x^2 + 10*x + 1) (x + (\x -> 2*x^2 + 10*x + 1) (y - (\x -> 2*x^2 + 10*x + 1) z) + (\x -> 2*x^2 + 10*x + 1) (z^2)) 

tôi chỉ đùa thôi, xin lỗi.

+3

Tôi chắc rằng những người chỉ dẫn của anh ấy sẽ ít vui mừng hơn về câu trả lời đó;) – Nate

+1

Đây chính xác là câu trả lời tôi đưa ra. Theo như tôi biết, câu hỏi này sẽ tóm tắt "ở đây, lấy mã thành ngữ này và làm cho nó tồi tệ hơn, chỉ để chứng minh rằng bạn biết X". Nếu giáo viên muốn kiểm tra xem tôi có biết X hay không, họ nên đặt câu hỏi trong đó X thực sự hữu ích/cần thiết. –

-1

Câu hỏi đó có vẻ hơi tò mò và thú vị đối với tôi. Vì vậy, tôi đang cố gắng để tìm ra những gì là tính toán lambda là, tìm một câu trả lời và muốn hiển thị nó để OP (tất cả các gợi ý đã được cho thấy thực sự, cảnh báo spoiler).

Thứ nhất, cho phép thử để xác định lại f:

λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) 
f :: 
    (Integer -> Integer) -> Integer -> Integer -> Integer -> Integer 

chức năng Vì vậy, chúng tôi đã có, trong đó có chức năng và 3 số và gửi lại câu trả lời. Sử dụng curring chúng ta có thể thêm g nét ngay tại đây, như f_new = f g:

λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1) 
f :: Integer -> Integer -> Integer -> Integer 

Chúng tôi đã hoàn tất. Hãy kiểm tra xem:

λ> f 0 0 0 
-13 

Câu trả lời là chính xác.

UPD:

Trong những ví dụ let chỉ là một cách để khai báo hàm trong các thông dịch viên, vì vậy câu trả lời cuối cùng là:.

f :: Num a => a -> a -> a -> a 
f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1) 
Các vấn đề liên quan