【问题标题】:Scrap Your Boilerplate in f#在 f# 中报废你的样板文件
【发布时间】:2011-04-05 12:47:50
【问题描述】:

我在 Haskell 编程语言中使用了 Scrap Your Boilerplate 和 Uniplate 库,我发现这种形式的通用编程在可区分联合上非常有用。 f# 编程语言中是否有等效库?

【问题讨论】:

    标签: f# generic-programming discriminated-union scrap-your-boilerplate


    【解决方案1】:

    我不知道;如果没有语言/编译器内置的支持,我希望唯一的选择是基于反射的版本。 (我不知道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 如何实现源代码的问题可在 community.haskell.org/~ndm/darcs/uniplate 获得。
    • 我接受了你的回答,因为我认为这是一个很好的方法——但我做了一些改变以使其正常工作:我用 'ot.IsSubclassOf(ft )' - 否则当 f 的参数类型(即 'a 比所传递的特定参数更通用)时匹配失败。
    • 首先近似地,Uniplate 是用魔法实现的。 :] 也就是说,Uniplate、SYB 和相关库大多作为反射功能的结构化、显式实现存在。 Haskell 不需要特殊支持(自动生成实例只是为了方便),但我不知道使用的技术是否存在于 F# 中,无论哪种方式,我都希望在现有的反射设施,如您在此处的示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-28
    相关资源
    最近更新 更多