2010-02-09 29 views
18

F # có cùng vấn đề với C# nơi bạn không thể trực tiếp sử dụng toán tử số học với các kiểu T chung không?F # có hỗ trợ số học chung không?

Bạn có thể viết hàm Sum chung để trả về tổng của bất kỳ giá trị nào hỗ trợ bổ sung số học không?

Trả lời

4

F # có một số hỗ trợ giới hạn cho việc này. Một giải pháp chung tốt có thể liên quan đến các lớp loại, mà không được hỗ trợ bởi CLR nói chung, hoặc F # nói riêng.

F # có toán tử số học quá tải sử dụng các hàm 'ràng buộc thành viên tĩnh' và 'nội tuyến'. Đây là ma thuật cho phép, ví dụ: toán tử + hoạt động trên cả hai số int s và float s. Bạn có thể viết các hàm inline có triển khai dựa trên toán tử được xây dựng trong toán tử và thực hiện một số tiến trình, nhưng nó không tầm thường để làm nói chung. Bạn có thể xem ví dụ: mã nguồn tới Array.sum (trong mảng.fs trong FSharp.Core) trong phân phối nguồn F # đi kèm với CTP để có được một cảm giác.

Xem thêm các 'hạn chế thành viên tĩnh' và 'mô phỏng các lớp học kiểu' một phần của câu trả lời này:

Functions with generic parameter types

cũng như bit khác nhau của thư viện như

http://msdn.microsoft.com/en-us/library/ee370581(VS.100).aspx

http://msdn.microsoft.com/en-us/library/ee340262(VS.100).aspx

2

Cơ chế tốt nhất mà tôi biết để thực hiện ing số học chung là loại lớp học, mà đáng buồn là cả C#, F #, cũng như thời gian chạy .Net trong hỗ trợ chung. Tuy nhiên, bạn có thể mô phỏng chúng mình bằng tay, như đã đề cập trong bài viết trên blog này:

Type Classes Are The Secret Sauce

kỹ thuật Điều đó sẽ làm việc trong C# 2.0 hoặc mới hơn (sử dụng các đại biểu vô danh/lambdas).

Thường thì mọi người chuyển sang giao diện, nhưng chạy vào một vài vấn đề

  1. Bạn không thể tuyên bố rằng loại hiện có thực hiện một giao diện, vì vậy bạn không thể xác định thể hiện của giao diện đó cho xây dựng trong các loại như int .
  2. Giao diện không thể hạn chế loại đối số khác đối với phương pháp.

Giao diện tuyên bố rằng, đối với tất cả triển khai, tất cả các phương thức trên giao diện đó đều có cùng loại tham số 'này'. Nếu Foo thực hiện một số giao diện, thì rõ ràng tham số 'this' phải là kiểu Foo để thực hiện. Nhưng không có cách nào để yêu cầu các thông số phương pháp khác cũng là thuộc loại Foo.

Type classes cho phép bạn (trong số những thứ khác) thực hiện loại ràng buộc này trên tất cả các tham số phương pháp, không chỉ tham số đầu tiên.

Như đã đề cập trong bài viết được trích dẫn trước đó, bạn có thể mô phỏng các lớp kiểu bằng cách chuyển các bảng chức năng dưới dạng đối số rõ ràng.

(Cộng đồng wiki: sẽ gửi một ví dụ từ bài viết mà dịch sang C# ở đây, nhưng đã hết thời gian với Giải thích dài dòng)

4

Bạn có thể làm một cái gì đó như thế này.

let inline sum<'a when 'a : (static member (+) : 'a -> 'a -> 'a)> a b = 
    a + b 

let result = sum<int> 3 4 

Tuy nhiên nếu tôi cố gắng let result = sum 3 4 tôi nhận được lỗi "type ambiguity inherent in the use of the operator '(+)'"

+2

Tôi nghĩ bạn cần sử dụng '^ a' thay vì' 'a' khi sử dụng các ràng buộc tĩnh trong F #, nhưng tôi có thể sai ... –

+0

Cả hai đều hoạt động trong trường hợp này. – gradbot

+5

Trong trường hợp cụ thể này, bạn thậm chí không cần phải xác định các tham số chung hoặc các ràng buộc bởi vì chúng có thể được suy ra: 'cho inline tổng a b = a + b' – kvb

8

Như brian đề cập, có một số được xây dựng trong hỗ trợ cho arithmethic generic và bạn có thể sử dụng 'chế tĩnh' cho phép bạn xác định một số generic chức năng chính mình (mặc dù điều này là một chút hạn chế). Ngoài ra, bạn cũng có thể sử dụng 'các liên kết số' động, chậm hơn một chút khi sử dụng trong một hàm, nhưng nó có thể được sử dụng độc đáo để xác định loại véc tơ hoặc ma trận của riêng bạn. Dưới đây là ví dụ:

#r "FSharp.PowerPack.dll" 
open Microsoft.FSharp.Math 

let twoTimesLarger (n:'a) (m:'a) = 
    let ops = GlobalAssociations.GetNumericAssociation<'a>() 
    let sel = if ops.Compare(n, m) > 0 then n else m 
    ops.Multiply(sel, ops.Add(ops.One, ops.One)) 

Trước tiên, chúng tôi cần tham khảo F # Thư viện PowerPack chứa chức năng. Sau đó, chúng tôi xác định một hàm chung với một chữ ký 'a -> 'a -> 'a. Dòng đầu tiên tự động nhận các phép toán số để làm việc với kiểu 'a (về cơ bản nó sử dụng một số bảng tra cứu có kiểu là khóa). Sau đó, bạn có thể sử dụng các phương thức của đối tượng hoạt động số để thực hiện những việc như phép nhân, phép cộng (Multiply, Add) và nhiều đối tượng khác. Các chức năng làm việc với bất kỳ số:

twoTimesLarger 3 4 
twoTimesLarger 2.3 2.4 
twoTimesLarger "a" "b" // Throws an exception! 

Khi bạn định nghĩa kiểu số của riêng bạn, bạn có thể xác định các hoạt động số của nó và đăng ký sử dụng GlobalAssociations.RegisterNumericAssociation. Tôi tin rằng điều này cũng có nghĩa là bạn sẽ có thể sử dụng F # Matrix<YourType>Vector<YourType> được tích hợp sau khi đăng ký hoạt động.

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