tipos textos texto tesis redactar redaccion partes estructura ejemplos ejemplo debe conclusion con como argumentos argumento argumentativos argumentativo argumentacion haskell

haskell - textos - ¿Cómo cambiar el orden de los argumentos?



texto argumentativo partes (2)

¿Qué pasa si quiero cambiar el orden de los argumentos en una función?

Hay flip

flip :: (a -> b -> c) -> b -> a -> c

pero no veo cómo hacer que funcione para un mayor número de argumentos. ¿Hay un método general para permutar los argumentos?


La mejor manera en general es simplemente hacerlo manualmente. Asume que tienes una función

f :: Arg1 -> Arg2 -> Arg3 -> Arg4 -> Res

y te gustaria

g :: Arg4 -> Arg1 -> Arg3 -> Arg2 -> Res

entonces escribes

g x4 x1 x3 x2 = f x1 x2 x3 x4

Si necesita una permutación particular varias veces, entonces, por supuesto, puede abstraerse de ella, como lo hace flip para el caso de dos argumentos:

myflip :: (a4 -> a1 -> a3 -> a2 -> r) -> a1 -> a2 -> a3 -> a4 -> r myflip f x4 x1 x3 x2 = f x1 x2 x3 x4


Si tienes ganas de editar las funciones después de que estén escritas, realmente deberías leer los excelentes combinadores de editor semántico de Conal Elliott.

http://conal.net/blog/posts/semantic-editor-combinators

De hecho, todos deberían leerlo de todos modos. Es un método realmente útil (que estoy abusando aquí). Conal usa más construcciones que solo result y flip a un efecto muy flexible.

result :: (b -> b'') -> ((a -> b) -> (a -> b'')) result = (.)

Supongamos que tengo una función que usa 3 argumentos

use3 :: Char -> Double -> Int -> String use3 c d i = c: show (d^i)

y me gustaría intercambiar los dos primeros, solo uso flip use3 como usted dice, pero si quisiera intercambiar el segundo y el tercero, lo que quiero es aplicar flip al resultado de aplicar use3 a su primer argumento .

use3'' :: Char -> Int -> Double -> String use3'' = (result) flip use3

Avancemos e intercambiemos los argumentos cuarto y quinto de una función use5 que usa 5.

use5 :: Char -> Double -> Int -> (Int,Char) -> String -> String use5'' :: Char -> Double -> Int -> String -> (Int,Char) -> String use5 c d i (n,c'') s = c : show (d ^ i) ++ replicate n c'' ++ s

Necesitamos aplicar flip al resultado de aplicar use5 a sus primeros tres argumentos, así que ese es el resultado del resultado del resultado:

use5'' = (result.result.result) flip use5

¿Por qué no guardar el pensamiento más tarde y definirlo?

swap_1_2 :: (a1 -> a2 -> other) -> (a2 -> a1 -> other) swap_2_3 :: (a1 -> a2 -> a3 -> other) -> (a1 -> a3 -> a2 -> other) --skip a few type signatures and daydream about scrap-your-boilerplate and Template Haskell swap_1_2 = flip swap_2_3 = result flip swap_3_4 = (result.result) flip swap_4_5 = (result.result.result) flip swap_5_6 = (result.result.result.result) flip

... y ahí es donde debes parar si te gusta la simplicidad y la elegancia. Tenga en cuenta que el other tipo podría ser b -> c -> d por lo que debido a la fabulosa Curry y la asociatividad correcta de -> , swap_2_3 funciona para una función que toma cualquier número de argumentos por encima de dos. Para algo más complicado, deberías escribir una función permutada a mano. Lo que sigue es solo por el bien de la curiosidad intelectual.

Ahora, ¿qué pasa con el intercambio de los argumentos segundo y cuarto? [Aparte: hay un teorema que recuerdo de mis lecciones de álgebra que cualquier permutación se puede hacer como la composición de intercambiar elementos adyacentes.]

Podríamos hacerlo así: paso 1: mueve 2 junto a 4 ( swap_2_3 )

a1 -> a2 -> a3 -> a4 -> otherstuff a1 -> a3 -> a2 -> a4 -> otherstuff

intercambialas usando swap_3_4

a1 -> a3 -> a2 -> a4 -> otherstuff a1 -> a3 -> a4 -> a2 -> otherstuff

luego intercambie 4 de nuevo a la posición 2 usando swap_2_3 nuevo:

a1 -> a3 -> a4 -> a2 -> otherstuff a1 -> a4 -> a3 -> a2 -> otherstuff

asi que

swap_2_4 = swap_2_3.swap_3_4.swap_2_3

Tal vez haya una manera más concisa de llegar directamente con muchos resultados y giros, ¡pero el juego aleatorio no lo encontré para mí!

De manera similar, para intercambiar 1 y 5 podemos mover 1 sobre 4, intercambiar con 5, mover 5 hacia atrás de 4 a 1.

swap_1_5 = swap_1_2.swap_2_3.swap_3_4 . swap_4_5 . swap_3_4.swap_2_3.swap_1_2

O si prefieres, puedes reutilizar swap_2_4 volteando en los extremos (intercambiando 1 con 2 y 5 con 4), swap_2_4 y luego volteando de nuevo en los extremos.

swap_1_5'' = swap_1_2.swap_4_5. swap_2_4 .swap_4_5.swap_1_2

Por supuesto que es mucho más fácil de definir.

swap_1_5'''' f a b c d e = f e b c d a

que tiene la ventaja de ser claro, coherente, eficiente y tiene una firma de tipo útil en ghci sin anotarlo explícitamente.

Sin embargo, esta fue una pregunta fantásticamente entretenida, gracias.