在 f# 中废弃你的样板 [英] Scrap Your Boilerplate in f#
问题描述
我使用了废掉你的样板
I've used the Scrap Your Boilerplate and Uniplate libraries in the Haskell programming language, and I would find that form of generic programming over discriminated unions to be really useful. Is there an equivalent library in the f# programming language?
推荐答案
我不知道;如果没有内置语言/编译器的支持,我希望唯一的选择是基于反射的版本.(我不知道 Uniplate 是如何实现的 - 你是吗?)
Not that I know of; without support built-in to the language/compiler, I expect the only alternative is a reflection-based version. (I don't know how Uniplate is implemented - do you?)
这是基于原始演示文稿示例的基于反射的版本的代码.我没有深入考虑它的局限性,但编写起来比我想象的要简单得多.
Here's the code for a reflection-based version based on the example from the original presentation. I have not thought deeply about its limitations, but this was much simpler to write than I would have guessed.
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
起作用的类型的每个节点继续,保留所有其他节点.
The everywhere
function traverses the entire structure of an arbitrary DU and applies the function f
to each node that is the type that f
works on, leaving all other nodes as-is.
这篇关于在 f# 中废弃你的样板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!