Estoy tratando de hacer lo que debe ser deslumbrantemente obvio en Haskell, que va desde Just [1]
y Just [2]
hasta Just [1, 2]
. Sin embargo, no puedo encontrar nada en línea ya que sigo encontrando páginas relacionadas pero inútiles. Entonces, ¿cómo lo logras?Fusionando/Anexando Justs en Haskell
Respuesta
Puede utilizar liftA2 (++)
:
liftA2 (++) :: Maybe [a] -> Maybe [a] -> Maybe [a]
liftA2
simplemente levanta una función binaria en un Applicative
. Applicative
s fueron diseñados para levantar funciones de argumentos arbitrarios en un contexto, por lo que son perfectos para esto. En este caso, el Applicative
que estamos usando es Maybe
. Para ver cómo funciona esto, podemos mirar a la definición:
liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
liftA2 f a b = f <$> a <*> b
(<$>)
simplemente levanta ninguna función en los valores puros a un funcionamiento en el interior f
: (a -> b) -> f a -> f b
. (Es sólo un alias para fmap
, si está familiarizado con Functor
s.) Para Maybe
:
_ <$> Nothing = Nothing
f <$> Just x = Just (f x)
(<*>)
es un poco más complicado: se aplica una función dentro de f
a un valor dentro de f
: f (a -> b) -> f a -> f b
. Para Maybe
:
Just f <*> Just x = Just (f x)
_ <*> _ = Nothing
(De hecho, f <$> x
es lo mismo que pure f <*> x
, que es Just f <*> x
para Maybe
.)
Por lo tanto, podemos ampliar la definición de liftA2 (++)
:
liftA2 (++) a b = (++) <$> a <*> b
-- expand (<$>)
liftA2 (++) (Just xs) b = Just (xs ++) <*> b
liftA2 (++) _ _ = Nothing
-- expand (<*>)
liftA2 (++) (Just xs) (Just ys) = Just (xs ++ ys)
liftA2 (++) _ _ = Nothing
De hecho, podemos usar estos operadores para levantar una función de cualquier cantidad de argumentos en cualquier Applicative
, j ust siguiendo el patrón de liftA2
. Esto se llama estilo aplicativo, y es muy común en el código Haskell idiomático. En este caso, podría ser incluso más idiomático usarlo directamente escribiendo (++) <$> a <*> b
, si a
y b
ya son variables. (Por otro lado, si está parcialmente su aplicación - por ejemplo, para pasar a una función de orden superior - a continuación, liftA2 (++)
es preferible.)
Cada Monad
es un Applicative
, por lo que si alguna vez se encuentra tratando de "levantar" una función en un contexto, Applicative
es probablemente lo que estás buscando.
mientras que la respuesta de @ ehird es grande, habría utilizado una solución noobish en la forma:
mergeJust a b = do
a' <- a
b' <- b
return (a' ++ b')
+1 incluso noobs, equipados con herramientas simples, pueden resolver este problema. También podría escribir lo mismo que una comprensión de mónada: '[a '++ b' | a '<- a, b' <- b] ' –
para expandir la solución a una lista de Just
s, se puede usar
fmap join $ sequence [Just[1],Just[2],Just[3]]
-- Just [1,2,3]
Como no fue mencionado en otras soluciones, lo diré aquí. La forma más sencilla de realizar su tarea, en mi opinión, es usar <>
(o mappend
) desde Data.Monoid
.
import Data.Monoid
Just [1,2] <> Just [7,8] == Just [1,2,7,8]
Sin embargo, tenga en cuenta que esta solución, a diferencia de la solución aplicativa de ehird, se provoque un cortocircuito en Nothing
valores.
Just [1,2] <> Nothing ---> Just [1,2]
--However
(++) <$> Just [1,2] <*> Nothing ---> Nothing
A veces este será el comportamiento adecuado, a veces no. –
- 1. en Haskell
- 2. Escribir un intérprete Haskell en Haskell
- 3. Ecuaciones guardadas en Haskell
- 4. Cola eficiente en Haskell
- 5. Catamorphism y en Haskell
- 6. ¿Qué significa ': ..' en Haskell?
- 7. Variables en Haskell
- 8. Computación acotada en Haskell
- 9. instalando dependencias en haskell
- 10. Cierres (en Haskell)
- 11. PNL Analizador en Haskell
- 12. ¿Doble mapa en haskell?
- 13. manejo en Haskell
- 14. Codificación SHA1 en Haskell
- 15. Proyectos útiles en Haskell
- 16. Y Combinator en Haskell
- 17. (emulado) ¿Macros en Haskell?
- 18. Autoindependiente Haskell en Vim
- 19. Combinar ordenar en Haskell
- 20. Cortocircuito (&&) en Haskell
- 21. Valor NILL en haskell
- 22. instancias huérfanas en Haskell
- 23. Haskell en ARM Beagleboard
- 24. valor inferior en Haskell
- 25. . contra $ en Haskell
- 26. Descomprimir GZip en Haskell
- 27. Cubesumming en Haskell
- 28. valores absolutos en Haskell
- 29. argumentos opcionales en Haskell
- 30. Sin puntos en Haskell
Awesome :) Gracias, me has salvado arrancándome el pelo. No suponga que conoce un equivalente para '[2]' y 'Just [3]' -> 'Just [2, 3]' ¿verdad? :) –
@DeanBarnes: '(2 :) <$> Simplemente [3]' –
¡Respuesta fantástica, gracias @ehird! Esta es básicamente mi referencia a partir de ahora :) –