Отбрось свой котел в f # - PullRequest
11 голосов
/ 30 августа 2010

Я использовал библиотеки Scrap Your Boilerplate и Uniplate на языке программирования Haskell, и я считаю, что такая форма универсального программирования для разграниченных объединений действительно полезна.Есть ли эквивалентная библиотека на языке программирования f #?

1 Ответ

11 голосов
/ 30 августа 2010

Не то, что я знаю; без поддержки, встроенной в язык / компилятор, я ожидаю, что единственной альтернативой будет версия на основе рефлексии. (Я не знаю, как реализовано 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, оставляя все остальные узлы как есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...