Intenté aprender F # pero me confundí al intentar distinguir entre plegar y reducir . Fold parece hacer lo mismo pero toma un parámetro adicional. ¿Existe una razón legítima para que existan estas dos funciones o están allí para dar cabida a personas de diferentes orígenes? (Por ejemplo: cadena y cadena en C #)
Aquí hay un fragmento de código copiado de la muestra:
let sumAList list =
List.reduce (fun acc elem -> acc + elem) list
let sumAFoldingList list =
List.fold (fun acc elem -> acc + elem) 0 list
printfn "Are these two the same? %A "
(sumAList [2; 4; 10] = sumAFoldingList [2; 4; 10])
f#
functional-programming
reduce
fold
Wallace
fuente
fuente

fold f a lse puede escribir comoreduce f a::l.folden términos dereducees más complicado que eso - ¡el tipo de acumulador defoldno tiene que ser el mismo que el tipo de cosas en la lista!Respuestas:
Foldtoma un valor inicial explícito para el acumulador mientrasreduceusa el primer elemento de la lista de entrada como valor inicial del acumulador.Esto significa que el acumulador y, por lo tanto, el tipo de resultado deben coincidir con el tipo de elemento de la lista, mientras que pueden diferir
foldporque el acumulador se proporciona por separado. Esto se refleja en los tipos:Además,
reducelanza una excepción en una lista de entrada vacía.fuente
fold, simplemente puede agregar ese valor inicial al comienzo de la lista yreduce¿ hacerlo ? ¿Qué sentido tienefoldentonces?'state -> 'a -> 'statepara pliegue vs'a -> 'a -> 'apara reducir, por lo que reducir restringe el tipo de resultado para que sea el mismo que el tipo de elemento. Vea la respuesta de Tomas Petricek a continuación.Además de lo que dijo Lee, puede definir
reduceen términos defold, pero no (fácilmente) al revés:El hecho de que
foldtome un valor inicial explícito para el acumulador también significa que el resultado de lafoldfunción puede tener un tipo diferente al tipo de valores en la lista. Por ejemplo, puede usar un acumulador de tipostringpara concatenar todos los números de una lista en una representación textual:Cuando se usa
reduce, el tipo de acumulador es el mismo que el tipo de valores en la lista; esto significa que si tiene una lista de números, el resultado tendrá que ser un número. Para implementar la muestra anterior,stringprimero tendría que convertir los números a y luego acumular:fuente
fold' & its ability to expressreducir '. Algunos idiomas tienen un concepto de quiralidad estructural (Haskell, te estoy mirando) que puedes doblar hacia la izquierda o hacia la derecha representado visualmente en esta wiki ( en.wikipedia.org/wiki/Fold_%28higher-order_function ). Con una construcción de identidad, los otros dos operadores FP "fundamentales" (filter y fmap) también se pueden implementar con una construcción de lenguaje de primera clase "fold" existente (todas son construcciones isomorfas). ( cs.nott.ac.uk/~pszgmh/fold.pdf ) Ver: HoTT, Princeton (Esta sección de comentarios es demasiado pequeña para contener ...)Veamos sus firmas:
Hay algunas diferencias importantes:
reducefunciona solo con un tipo de elementos, los elementos de lista y acumuladorfoldpueden ser de diferentes tipos.Con
reduce, aplicas una funciónfa cada elemento de la lista empezando por el primero:f (... (f i0 i1) i2 ...) iN.Con
fold, se aplicafpartiendo del acumuladors:f (... (f s i0) i1 ...) iN.Por lo tanto,
reduceda como resultado unaArgumentExceptionlista vacía. Además,foldes más genérico quereduce; que puede utilizarfoldpara implementarreducefácilmente.En algunos casos, el uso
reducees más sucinto:o más conveniente si no hay ningún acumulador razonable:
En general,
foldes más potente con un acumulador de tipo arbitrario:fuente
foldes una función mucho más valiosa quereduce. Puede definir muchas funciones diferentes en términos defold.reducees solo un subconjunto defold.Definición de pliegue:
Ejemplos de funciones definidas en términos de pliegue:
fuente
folddiferente deList.foldcomo el tipo deList.foldes('a -> 'b -> 'a) -> 'a -> 'b list -> 'a, pero en su caso('a -> 'b -> 'b) -> 'b -> 'a list -> 'b. Solo para hacerlo explícito. Además, su implementación de append es incorrecta. Funcionaría si le agregas un enlace, por ejemploList.collect id (fold (fun x y -> x :: y) [] [xs;ys]), o reemplazas cons con el operador append. Por lo tanto, adjuntar no es el mejor ejemplo de esta lista.