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. Futuros en Haskell
- 4. instalando dependencias en haskell
- 5. Mapas infinitos en Haskell
- 6. valores absolutos en Haskell
- 7. ¿Doble mapa en haskell?
- 8. Parse XML en Haskell
- 9. funciones externas en haskell?
- 10. 'Repetir' en Haskell?
- 11. Catamorphism y en Haskell
- 12. ¿Qué significa ': ..' en Haskell?
- 13. Variables en Haskell
- 14. Cierres (en Haskell)
- 15. Sin puntos en Haskell
- 16. Cola eficiente en Haskell
- 17. autorreferencia en Haskell funciona
- 18. manejo en Haskell
- 19. Dependencia funcional en Haskell
- 20. framework MVC en Haskell
- 21. Excepciones puras en Haskell
- 22. instancias huérfanas en Haskell
- 23. (emulado) ¿Macros en Haskell?
- 24. Guardar gráficos en Haskell
- 25. recursiva IO en Haskell
- 26. Computación acotada en Haskell
- 27. Acumuladores en Haskell
- 28. Autoindependiente Haskell en Vim
- 29. PNL Analizador en Haskell
- 30. Discos dispersos 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 :) –