haskell - Ayuda en la comprensión de código de pointfree
(1)
Al jugar con Pointfree me presentaron un código que no puedo entender.
:pl map (/x -> x * x) [1..10]
-- map (join (*)) [1..10]
Mi principal problema es que no entiendo cómo funciona la join
aquí. Entiendo que ''elimina'' una capa de una envoltura monádica ( m (ma)
a ma
). Me parece que se reduce a algo como [1..10] >>= (/x -> [x * x])
, pero realmente no entiendo cómo se introduce la "capa extra". Obtengo esa join x = x >>= id
, pero luego sigo atascado en cómo "duplica" cada valor para que (*)
obtenga dos argumentos. Esto me ha estado molestando durante aproximadamente media hora y me siento molesto conmigo mismo, porque siento que tengo todas las piezas del rompecabezas pero parece que no puedo encajarlas ...
PD No te preocupes, realmente no usaría esta versión de pointfree, esto es pura curiosidad y un intento de entender mejor a Haskell.
join
usa la instancia de Monad
para (->) a
, como se define en Control.Monad.Instances
. La instancia es similar a Reader
, pero sin un contenedor explícito. Se define así:
instance Monad ((->) a) where
-- return :: b -> (a -> b)
return = const
-- (>>=) :: (a -> b) -> (b -> a -> c) -> (a -> c)
f >>= g = /x -> g (f x) x
Si ahora reduce la join
usando esta instancia:
join
(>>= id)
flip (/f g x -> g (f x) x) (/a -> a)
(/f x -> (/a -> a) (f x) x)
(/f x -> f x x)
Como puede ver, la instancia para (->) a
hace que se una a una función que aplica un argumento dos veces. Debido a esto, join (*)
es simplemente /x -> x * x
.