Programación funcional: ¿Cómo implementas este fragmento imperativo con Haskell idiomático? ¿Puedo decir que es una operación establecida como la inyección? ¿Cómo puedo abstraerlo como una estructura de datos?

Bueno, necesitas resolver algunos pequeños problemas. El problema tal como se describe no es imperativo en absoluto (a menos que los pasos 1 y 3 involucren algún tipo de IO en lugar de simplemente darse).

* Realice cualquier normalización de una oración de entrada (normalice mayúsculas, minúsculas o coaccione caracteres no alfanuméricos a delimitadores)
* Tokenizar una oración normalizada (dividida en cada palabra)
* Convierta una lista de estos tokens (palabras) en una estructura de datos eficiente para su algoritmo de coincidencia (un Conjunto)
* Calcular el tamaño de la intersección para dos conjuntos
* Calcular el par máximo (puntaje, oración) dada una lista de ellos

Estas son una o dos líneas cada una en Haskell, y no debería necesitar usar más allá de Prelude, Data.Char, Data.Set y quizás Data.List. Suena sospechosamente como tarea, por lo que no voy a proporcionarle ningún código aquí, pero debería poder hacerlo en aproximadamente 20 líneas (incluida una cantidad razonable de espacios en blanco, pero no comentarios).

Tenga en cuenta que el algoritmo propuesto anteriormente es equivalente, pero no funciona exactamente de la misma manera que ha descrito, ya que las oraciones completas se comparan de manera eficiente usando la intersección de Set en lugar de hacerlo palabra por palabra.

Si quieres practicar tu Haskell, te sugiero que pruebes el ejercicio. Como sus envíos reciben una revisión del código, debe aprender cómo se ve el código más idiomático con bastante rapidez. Hay algunos problemas similares (pero no idénticos) a esto allí.

Hay una cosa llamada la Transformación de Schwartz que es útil para ordenar. Imagine que tiene una función f :: a -> b con b con un orden y una lista as :: [a] y le gustaría ordenar su lista por el resultado de cada a fa lugar del orden de a a sí mismos.

En esta circunstancia, usa una Transformación Schwartziana.

Primero, asigna la lista de a s contigua al resultado de invocar f en cada valor con el valor en sí:

map (\a -> (a, fa)) as

luego define el orden de esos (a, b) pares para que sea el orden del segundo valor ignorando el primero. Podemos usar las funciones sortBy y de comparing Haskell para esto

sortBy (comparing snd) (map (\a -> (a, fa)) as)

Finalmente, solo desea recortar esos valores de agujas b

map fst (sortBy (comparing snd) (map (\a -> (a, fa)) as))

Y esa es una transformación de Schwartz. Es casi lo que está haciendo aquí, excepto (1) que desea utilizar maximizeBy lugar de sortBy y (2) no necesita recortar los valores b al final.

Entonces, lo que sugiero que hagas es crear una función basada en las palabras de la oración A que “evalúa” cualquier otra oración. Si dejas que esa función sea f en tu Transformación Schwartziana, terminarás con una función que clasifica las oraciones B por “Una similitud”. Luego, si modifica la transformación de la manera que sugerí anteriormente, tendrá su respuesta.

Probablemente podría hacerlo en una sola línea si no le importara un poco jugar al golf. ¡Buena suerte!