2013-08-30 26 views
14

F # làm cho nó dễ dàng để xác định các loại nhưLàm thế nào để làm xác nhận đối số của F # hồ sơ

type coords = { X : float; Y : float } 

nhưng làm thế nào để xác định ràng buộc/kiểm tra đối số cho các nhà xây dựng mà không đi sâu vào cú pháp định nghĩa lớp tiết hơn? Ví dụ. nếu tôi muốn coords bắt đầu từ (0,0) hoặc ném một ngoại lệ. Hơn nữa, nếu tôi thay đổi định nghĩa của tôi thành một lớp tôi cần phải thực hiện Equals() vv tất cả các mã tấm nồi hơi tôi không muốn (và tôi có trong C# mà tôi đang cố gắng để có được từ) .

+1

có thể trùng lặp của [Có thể thực thi một bản ghi tôn trọng một số bất biến?] (Http://stackoverflow.com/questions/13925361/is-it-possible-to-enforce-that-a-record-respects -some-invariants) –

+0

Đây là bản sao của câu hỏi khác. Bỏ phiếu để đóng. –

Trả lời

13

Bạn có thể làm cho việc thực hiện tư nhân. Bạn vẫn nhận được sự bình đẳng về cấu trúc nhưng bạn mất quyền truy cập trường trực tiếp và đối sánh mẫu. Bạn có thể khôi phục khả năng đó bằng các mẫu hoạt động.

//file1.fs 

type Coords = 
    private { 
    X: float 
    Y: float 
    } 

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] 
module Coords = 
    ///The ONLY way to create Coords 
    let create x y = 
    check x 
    check y 
    {X=x; Y=y} 

    let (|Coords|) {X=x; Y=y} = (x, y) 

//file2.fs 

open Coords 
let coords = create 1.0 1.0 
let (Coords(x, y)) = coords 
printfn "%f, %f" x y 
+2

Đó là cách giải quyết tốt Daniel. Ước gì tôi nghĩ ra nó. –

+3

Cảm ơn, cảm giác ruột của tôi cho tôi biết điều này rất phức tạp và không phải là một cách tiếp cận rất điển hình để tạo ra các loại? Tôi đoán làm cho một lớp học và thực hiện Equals là thích hợp hơn .. hoặc thực thi rằng tất cả các loại trong chương trình của tôi được xây dựng thông qua một số phương pháp tạo chung? –

+0

Rất hiếm, vâng, nhưng chỉ phức tạp khi bạn thực hiện nó. Tôi nghĩ rằng việc triển khai riêng tư là một tính năng tốt và hữu ích cho một số trường hợp được thừa nhận không phổ biến. – Daniel

4

Bạn phải sử dụng cú pháp định nghĩa lớp:

type coords(x: float, y: float) = 
    do 
    if x < 0.0 then 
     invalidArg "x" "Cannot be negative" 
    if y < 0.0 then 
     invalidArg "y" "Cannot be negative" 

    member this.X = 
    x 
    member this.Y = 
    y 
+2

nếu tôi thay đổi định nghĩa của mình thành một lớp, tôi cần phải thực hiện Equals(), v.v. tất cả mã tấm nồi hơi tôi không muốn (và tôi có trong C# mà tôi đang cố gắng tránh xa). –

+0

Có, bạn phải làm điều đó. Nếu bạn muốn đóng gói/ẩn dữ liệu hướng đối tượng, bạn cần có các công cụ C# giống như đối tượng, không có cách nào xung quanh. Điều tốt đẹp trong F # là bạn CÓ THỂ làm điều đó. – MiMo

+4

vì vậy những gì sẽ là F # cách? định nghĩa một lớp hoặc xác định hàm tạo trong cùng một mô-đun như bản ghi và hy vọng mọi người sử dụng phương thức tạo? –

5

Có một chuỗi gọi là Designing with Types trên F# for fun and profit. Trong phần "Buộc sử dụng hàm tạo", nó đề xuất sử dụng hàm xây dựng - đó là nơi các xác nhận hợp lệ đi trước khi loại được khởi tạo. Để giữ cho mọi người từ các loại instantiating trực tiếp, nó khuyến nghị hoặc đặt tên quy ước hoặc tập tin chữ ký.

Bạn có thể tìm thấy một số bài viết và ví dụ liên quan hơn bằng cách googling "thiết kế theo hướng miền f #".

Lưu ý rằng tôi đến từ C#/không áp dụng F # cho lớp miền của chúng tôi (chưa;) Tôi thực sự không thể biết cách một trong các phương pháp được đề xuất sẽ hoạt động trong một dự án lớn hơn. Một số điều chắc chắn dường như .. khác nhau trong thế giới mới dũng cảm này.

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