我用过了 报废你的锅炉 和Haskell编程语言中的Uniplate库,我会发现通过有区别的联合的泛型编程形式非常有用。 f#编程语言中是否有等效的库?
我用过了 报废你的锅炉 和Haskell编程语言中的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
继续工作,让所有其他节点保持原样。
从来没听说过;如果没有内置于语言/编译器的支持,我希望唯一的替代方案是基于反射的版本。 (我不知道怎么做 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
继续工作,让所有其他节点保持原样。