2010-09-29 8 views
16

F # le permite convertir operadores en funciones rodeándolos con (): por ejemplo, (+) es del tipo int -> int -> int.Usar lista contra operadores (a :: b) como una función

¿Es posible hacer esto con el operador de listas contra, ::?

No se comporta como un operador binario normales:

FSI> (::);; 

    (::);; 
    -^^ 

c:\temp\stdin(3,2): error FS0010: Unexpected symbol '::' in expression. 
Expected ')' or other token. 

Y el método List.Cons toma una tupla; no es curry

(Es útil poder hacer esto. Por ejemplo, puede usarlo para implementar map in terms of fold).

+0

¿No puedes escribir un pequeño contenedor alrededor de '::' o 'List.Cons'? – leppie

+0

Ookay, esto es realmente extraño. Puedes simplemente 'divertir x y -> x :: y' pero no tengo idea de por qué hay una inconsistencia tan inconsistente. ¿Tal vez porque '::' se puede usar en emparejamientos de patrones y se trata de manera especial? Pero eso aún no sería razón. – Dario

+0

Interesante pregunta. Esto funciona para el pensamiento concat '(@)'. – Stringer

Respuesta

16

parafraseado de http://cs.hubfs.net/forums/permalink/11713/11713/ShowThread.aspx#11713

(::) es una unión 'constructor' discriminado para el list<'a> type, y así planteó la cuestión de si un valor de función de sus argumentos se deben al curry (como +) o tupled (como todos los constructores DU). De cualquier manera, parece sospechoso/inesperado para algunas personas, por lo que F # simplemente no permite la construcción.

Por supuesto, siempre puedes escribir, p.

let cons x y = x :: y 

y utilizar cons, o simplemente utilizar un lambda fun x y -> x::y, si desea una "función de prefijo al curry de dos argumentos" para esto.

6

Lamentablemente, no, no se puede. :: no es un operador, sino una "palabra clave simbólica" de acuerdo con la gramática del lenguaje (consulte la sección 3.6 of the spec), al igual que :?> y algunas otras. Sin embargo, el lenguaje no parece completamente coherente aquí, ya que hay algunas palabras clave simbólicas que se pueden tratar como si fueran operadores (al menos (*) y (<@ @>)).

4

:: y [] pueden ser representados por List<_>.Cons y List<_>.Empty respectivamente. Tenga en cuenta que el primero toma una tupla como argumento. Estos están aquí para que las listas se puedan crear en idiomas distintos de F #.

> List.Cons(4, List.Empty);; 
val it : int list = [4] 

> 4::[];; 
val it : int list = [4] 

> List<int>.Cons(4, List<int>.Empty);; 
val it : int list = [4] 

> List.Cons;; 
val it : 'a * 'a list -> 'a list = <fun:[email protected]> //' 

> List<int>.Empty;; 
val it : int list = [] 
+0

Gracias. Tuve una prolbem convirtiendo ML op :: a F # donde (fun x y -> x :: y) no se pudo compilar, pero List <_>. Las cosas funcionaron. –

Cuestiones relacionadas