2010-03-03 26 views
15

Duplicar posible:
In Functional Programming, what is a functor?¿Podría explicarme los funtores OCaml?

No sé mucho acerca de OCaml, he estudiado F # durante algún tiempo y lo entendía del todo.

Dicen que F # pierde el modelo de functor, que está presente en OCaml. Intenté averiguar qué es exactamente el functor, pero la wikipedia y los tutoriales no me sirvieron de mucho.

¿Podría por favor iluminar ese misterio para mí? Gracias de antemano :)

EDIT:

he cogido el punto, thx a todos los que me ayudaron. Puede cerrar la pregunta como duplicado exacto de: In Functional Programming, what is a functor?

+0

No soy un F # ni gurú OCaml por lo gané Esto lo hago como una respuesta formal, pero estoy pensando que http://blog.matthewdoig.com/?p=152 puede ayudarlo un poco a explicar los funtores y cómo F # soluciona su ausencia. –

+0

He leído ese artículo primero, también está blog.matthewdoig.com/?p=155. Estoy a medio camino para entender eso :) – Bubba88

Respuesta

12

Los módulos son módulos parametrizados por módulos, es decir, una reflexión de módulos a módulos (la función normal es la reflexión de valores a valores, la función polimórfica es reflejo de tipos a funciones normales).

Véase también ocaml-tutorial on modules.

Examples in the manual son útiles también.

+0

Llegué 10 segundos tarde :-) No soy un especialista, y entendí esta explicación. – yogsototh

+2

Esta es una buena explicación de lo que son * funtores * de OCaml, y para qué sirven * es la programación de estructuras de datos genéricas (consulte la implementación de Set en la biblioteca estándar de OCaml, quizás sea el ejemplo más simple de functor) y generalmente una solución alternativa eficiente y estáticamente verificada para muchos problemas que también podría resolver con programación orientada a objetos. –

+0

Desearía tener esa suerte) ... Entonces, si lo entiendo de la manera correcta: los funtores son la forma de crear nuevos módulos al parametrizar módulos existentes como 'Set'? – Bubba88

29

Si viene de un universo OOP, entonces probablemente ayude a pensar en un módulo como análogo a una clase estática. Similar a las clases estáticas .NET, el módulo OCaml tiene constructores; a diferencia de .NET, los módulos OCaml pueden aceptar parámetros en sus constructores. Un functor es un nombre que suena aterrador para el objeto que pasa al constructor del módulo.

Así, utilizando el ejemplo canónico de un árbol binario, nos escribimos normalmente en C# como esto:

type 'a tree = 
    | Nil 
    | Node of 'a tree * 'a * 'a tree 

module Tree = 
    let rec insert v = function 
     | Nil -> Node(Nil, v, Nil) 
     | Node(l, x, r) -> 
      if v < x then Node(insert v l, x, r) 
      elif v > x then Node(l, x, insert v r) 
      else Node(l, x, r) 

fino y elegante. Pero, ¿cómo sabe F # cómo comparar dos objetos del tipo 'a con los operadores < y >?

Detrás de las escenas, el hacer algo como esto:

> let gt x y = x > y;; 

val gt : 'a -> 'a -> bool when 'a : comparison 

Muy bien, así que si usted tiene un objeto de tipo Person la que no implementa la interfaz en particular? ¿Qué pasaría si quisieras definir la función de clasificación sobre la marcha?Un enfoque es sólo para pasar en el comparador de la siguiente manera:

let rec insert comparer v = function 
     | Nil -> Node(Nil, v, Nil) 
     | Node(l, x, r) -> 
      if comparer v x = 1 then Node(insert v l, x, r) 
      elif comparer v x = -1 then Node(l, x, insert v r) 
      else Node(l, x, r) 

Se funciona, pero si usted está escribiendo un módulo para las operaciones de árboles con parte, las operaciones de búsqueda, extracción, etc., que requieren que los clientes pasan en una función de pedido cada vez que llaman a algo.

Si F # apoyado funtores, su sintaxis hipotética podría tener este aspecto:

type 'a Comparer = 
    abstract Gt : 'a -> 'a -> bool 
    abstract Lt : 'a -> 'a -> bool 
    abstract Eq : 'a -> 'a -> bool 

module Tree (comparer : 'a Comparer) = 
    let rec insert v = function 
     | Nil -> Node(Nil, v, Nil) 
     | Node(l, x, r) -> 
      if comparer.Lt v x then Node(insert v l, x, r) 
      elif comparer.Gt v x then Node(l, x, insert v r) 
      else Node(l, x, r) 

Todavía en la sintaxis hipotética, necesitará crear su módulo como tal:

module PersonTree = Tree (new Comparer<Person> 
    { 
     member this.Lt x y = x.LastName < y.LastName 
     member this.Gt x y = x.LastName > y.LastName 
     member this.Eq x y = x.LastName = y.LastName 
    }) 

let people = PersonTree.insert 1 Nil 

Desafortunadamente, F # doesn No admite funtores, por lo que debe recurrir a algunas soluciones desordenadas. Para el escenario anterior, casi siempre almacenaría el "funtor" en mi estructura de datos con algunas funciones auxiliares auxiliares para asegurarse de que se copia todo correctamente:

type 'a Tree = 
    | Nil of 'a -> 'a -> int 
    | Node of 'a -> 'a -> int * 'a tree * 'a * 'a tree 

module Tree = 
    let comparer = function 
     | Nil(f) -> f 
     | Node(f, _, _, _) -> f 

    let empty f = Nil(f) 

    let make (l, x, r) = 
     let f = comparer l 
     Node(f, l, x, r) 

    let rec insert v = function 
     | Nil(_) -> make(Nil, v, Nil) 
     | Node(f, l, x, r) -> 
      if f v x = -1 then make(insert v l, x, r) 
      elif f v x = 1 then make(l, x, insert v r) 
      else make(l, x, r) 

let people = Tree.empty (function x y -> x.LastName.CompareTo(y.LastName)) 
+4

Gracias por este útil ejemplo. Has logrado hacerlo sin una línea de código Ocaml, huh)) – Bubba88

+4

¿En qué se diferencia esto de aceptar una instancia de IEqualityComparer, por ejemplo, en el constructor? Podría implementarse ad-hoc utilizando expresiones de objetos. – Daniel

+6

@ Daniel: ese es básicamente el punto. El functor OCaml es básicamente lo mismo que pasar algún tipo de objeto al constructor de un módulo. Pero como las clases estáticas de F # modules == .NET y los constructores estáticos de .NET no aceptan parámetros en sus constructores, debe pasar por aros para obtener el mismo tipo de funcionalidad. – Juliet

Cuestiones relacionadas