Scrapper vos boilerplate en f #
-
02-10-2019 - |
Question
Je l'ai utilisé Scrap Votre boilerplate et les bibliothèques Uniplate dans la langue de programmation Haskell, et je trouverais cette forme de programmation générique sur les syndicats discriminés pour être vraiment utile. Y at-il une bibliothèque équivalent dans le langage de programmation f #?
La solution
Pas que je sache; sans soutien intégré au langage / compilateur, je pense la seule alternative est une version de réflexion. (Je ne sais pas comment Uniplaque est mis en œuvre - avez-vous)
Voici le code pour une version de réflexion basée sur l'exemple de la présentation originale. Je ne l'ai pas profondément réfléchi à ses limites, mais cela était beaucoup plus simple à écrire que je l'aurais deviné.
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
La fonction everywhere
traverse toute la structure d'un DU arbitraire et applique la fonction f
à chaque noeud qui est du type qui fonctionne sur f
, en laissant tous les autres nœuds tels quels.