我已经在Haskell编程语言中使用了Scrap Your Boilerplate和Uniplate库,并且我发现基于有区别的并集的泛型编程形式确实很有用。 f#编程语言中是否有等效的库?

最佳答案

从来没听说过;如果没有语言/编译器内置的支持,我希望唯一的选择是基于反射的版本。 (我不知道Uniplate是如何实现的-对吗?)

这是基于原始演示示例的基于反射版本的代码。我没有对它的局限性进行过深入的思考,但这比我想像的要简单得多。

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
everywhere函数遍历任意DU的整个结构,并将f函数应用于f所处理的类型的每个节点,而所有其他节点保持原样。

关于f# - 在F#中报废样板,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3596718/

10-10 16:15