He utilizado las bibliotecas Scrap Your Boilerplate y Uniplate en el lenguaje de programación Haskell, y me parece que esta forma de programación genérica sobre las uniones discriminadas es realmente útil. ¿Hay una biblioteca equivalente en el lenguaje de programación f #?Deseche su plantilla en f #
11
A
Respuesta
11
No es que yo sepa; sin compatibilidad incorporada al lenguaje/compilador, espero que la única alternativa sea una versión basada en la reflexión. (No sé cómo se implementa Uniplate, ¿verdad?)
Aquí está el código de una versión basada en la reflexión basada en el ejemplo de la presentación original. No he pensado profundamente acerca de sus limitaciones, pero esto fue mucho más simple de lo que hubiera imaginado.
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 función everywhere
atraviesa toda la estructura de un DU arbitraria y aplica la función f
a cada nodo que es el tipo que f
funciona en, dejando todos los demás nodos como está.
Cuestiones relacionadas
- 1. ¿Deseche su equivalente en Scala?
- 2. Git - deseche archivos añadidos
- 3. especialice una plantilla de miembro sin especializar su padre
- 4. C++ clase con plantilla no puede encontrar su constructor
- 5. Make * ALL * Wordpress Categories usa su plantilla de categoría principal
- 6. lambdas recursivas en F #
- 7. Plantilla de plantilla C++ Función
- 8. #indent "off" en F #
- 9. f Demostrando (f bool) = bool
- 10. F # y ADO.NET - idiomático F #
- 11. F # operator "?"
- 12. mixin o rasgo en F #
- 13. Llamar a una función desde su nombre como una cadena en f #
- 14. Accediendo a un espacio de nombres que contenga .base en su nombre desde F #
- 15. soporte macro en F #
- 16. FirstOrDefault En F #
- 17. Programación dinámica en F #
- 18. Igualdad estructural en F #
- 19. Listas cíclicas en F #
- 20. inmutable en F #
- 21. Ordenando tuplas en F #
- 22. módulos genéricos en F #
- 23. Bash simple - para f * en
- 24. plantilla de especialización de clase de plantilla
- 25. Programación funcional en C++ 11, estilo F #
- 26. F # - Muestra los resultados completos en la ventana interactiva F #
- 27. por qué "f = f ++" no es seguro en c?
- 28. Transformar la función 2d spline f (t) en f (x)
- 29. ¿Qué significa el .f en 1000.f? C++
- 30. Diferentes resultados usando f @ expr y expr // f en Mathematica
Esta es una buena sugerencia, tendré que pensar en las implicaciones de rendimiento de tal enfoque. Probablemente no importe para mi uso particular en cualquier caso. –
re: su pregunta sobre cómo se implementa Uniplate, la fuente está disponible en http://community.haskell.org/~ndm/darcs/uniplate/. –
He aceptado su respuesta ya que creo que es un buen enfoque, pero hago un cambio para que funcione correctamente: Reemplacé 'ft = ot' con 'ot.IsSubclassOf (ft)' - de lo contrario no coincide cuando el tipo de argumento de f, es decir, 'a es más genérico que el argumento específico que se pasa. –