2010-08-29 26 views

Trả lời

11

Tôi không biết; mà không có hỗ trợ được xây dựng trong ngôn ngữ/trình biên dịch, tôi hy vọng sự thay thế duy nhất là một phiên bản dựa trên sự phản chiếu. (Tôi không biết làm thế nào Uniplate được thực hiện - phải không?)

Đây là mã cho một phiên bản dựa trên phản chiếu dựa trên ví dụ từ bản trình bày gốc. Tôi đã không suy nghĩ sâu sắc về những hạn chế của nó, nhưng điều này đơn giản hơn nhiều so với những gì tôi đoán được.

type Company = C of Dept list 
and Dept = D of Name * Manager * SubUnit list 
and SubUnit = | PU of Employee | DU of Dept 
and Employee = E of Person * Salary 
and Person = P of Name * Address 
and Salary = S of float 
and Manager = Employee 
and Name = string 
and Address = string 

let data = C [D("Research",E(P("Fred","123 Rose"),S 10.0), 
        [PU(E(P("Bill","15 Oak"),S 5.0))])] 
printfn "%A" data 

open Microsoft.FSharp.Reflection 
let everywhere<'a,'b>(f:'a->'a, src:'b) = // ' 
    let ft = typeof<'a>    // ' 
    let rec traverse (o:obj) = 
     let ot = o.GetType() 
     if ft = ot then 
      f (o :?> 'a) |> box // ' 
     elif FSharpType.IsUnion(ot) then 
      let info,vals = FSharpValue.GetUnionFields(o, ot) 
      FSharpValue.MakeUnion(info, vals |> Array.map traverse) 
     else 
      o 
    traverse src :?> 'b  // ' 

let incS (S x) = S(x+1.0) 

let newData = everywhere(incS, data) 
printfn "%A" newData 

Các everywhere chức năng đi qua toàn bộ cấu trúc của một DU độc đoán và áp dụng chức năng f cho mỗi nút đó là loại mà f hoạt động trên, để lại tất cả các nút khác như nó vốn có.

+0

Đây là một gợi ý tốt, tôi sẽ phải suy nghĩ về những tác động hiệu quả của cách tiếp cận như vậy. Nó có lẽ không quan trọng cho usecase cụ thể của tôi anyway. –

+0

re: câu hỏi của bạn về cách Uniplate được triển khai, nguồn có sẵn tại http://community.haskell.org/~ndm/darcs/uniplate/. –

+0

Tôi đã chấp nhận câu trả lời của bạn vì tôi nghĩ đó là cách tiếp cận tốt - nhưng tôi thực hiện thay đổi để hoạt động chính xác: Tôi đã thay thế 'ft = ot' bằng 'ot.IsSubclassOf (ft)' - ngược lại không khớp khi kiểu đối số của f, tức là 'a là tổng quát hơn so với đối số cụ thể được chuyển. –

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