Para activar una función
func x y z = (some expression in x, y and z)
en forma libre puntos, por lo general trato de seguir lo que se hace para el último parámetro z
y escribir la función como
func x y z = (some function pipeline built using x and y) z
entonces puedo cancelar la z
s para obtener
func x y = (some function pipeline built using x and y)
Luego, repetir g el proceso para yyx debe terminar con func
en forma libre de puntos.Una transformación esencial reconocer en este proceso es:
f z = foo $ bar z -- or f z = foo (bar z)
<=> f z = foo . bar $ z
<=> f = foo . bar
También es importante recordar que la evaluación parcial, se puede "romper" el último argumento a una función:
foo $ bar x y == foo . bar x $ y -- foo applied to ((bar x) applied to y)
Para su especial función, tenga en cuenta que el flujo k
y t
pasan por:
ord
Aplicar a cada uno de ellos
- Añadir los resultados
- Reste 2 * a
- tomar el resultado mod 26
- Añadir un
- Aplicar
chr
Así como un primer intento de simplificar, se obtiene:
func k t = chr . (+a) . (`mod` 26) . subtract (2*a) $ ord k + ord t
Tenga en cuenta que puede evitar flip
usando una sección en mod
, y las secciones que usan -
se desordenan en Haskell por lo que hay una función subtract
(chocan con la sintaxis para escribir números negativos: (-2)
significa negativo 2, y no es lo mismo que subtract 2
).
En esta función, ord k + ord t
es un excelente candidato para el uso de Data.Function.on
(link). Este combinador de utilidad nos permite reemplazar ord k + ord t
con una función aplicada a k
y t
:
func k t = chr . (+a) . (`mod` 26) . subtract (2*a) $ ((+) `on` ord) k t
Ahora estamos muy cerca de tener
func k t = (function pipeline) k t
y por lo tanto
func = (function pipeline)
Desafortunadamente Haskell es un poco complicado cuando se trata de componer una función binaria con una secuencia de funciones unarias, pero hay un truco (veré si puedo encontrar un buena referencia para ello), y nos encontramos con:
import Data.Function (on)
func = ((chr . (+a) . (`mod` 26) . subtract (2*a)) .) . ((+) `on` ord)
que es casi una buena canalización función libre de punto limpio, a excepción de que la composición truco feo. Al definir el operador .:
sugerido en los comentarios on this page, esto arregla un poco para:
import Data.Function (on)
(.:) = (.).(.)
func = (chr . (+a) . (`mod` 26) . subtract (2*a)) .: ((+) `on` ord)
Para pulir esto un poco más, se podría añadir algunas funciones de ayuda a separar la letra < - conversión> Int desde el Caesar cipher aritmética . Por ejemplo: letterToInt = subtract a . ord
¿Por qué le gustaría dejarlo sin puntos? – yfeldblum
Porque poder escribir código sin puntos parece una de las propiedades de un buen programador Haskell. – Igor
A veces, el código sin puntos es más claro que su alternativa sin puntos, y luego es una buena idea usar estilos sin puntos. Este no es uno de esos momentos. – dave4420