Suma si todos los valores son justos
Definir la función
1 |
sumaSiTodosJustos :: (Num a, Eq a) => [Maybe a] -> Maybe a |
tal que (sumaSiTodosJustos xs) es justo la suma de todos los elementos de xs si todos son justos (es decir, si Nothing no pertenece a xs) y Nothing en caso contrario. Por ejemplo,
1 2 |
sumaSiTodosJustos [Just 2, Just 5] == Just 7 sumaSiTodosJustos [Just 2, Just 5, Nothing] == Nothing |
Soluciones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
import Data.Maybe (catMaybes, isJust, fromJust) import Test.QuickCheck (quickCheck) -- 1ª solución -- =========== sumaSiTodosJustos1 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos1 xs | todosJustos xs = Just (sum [x | (Just x) <- xs]) | otherwise = Nothing -- (todosJustos xs) se verifica si todos los elementos de xs son justos -- (es decir, si Nothing no pertenece a xs) y Nothing en caso -- contrario. Por ejemplo, -- todosJustos [Just 2, Just 5] == True -- todosJustos [Just 2, Just 5, Nothing] == False -- 1ª definición de todosJustos: todosJustos1 :: Eq a => [Maybe a] -> Bool todosJustos1 = notElem Nothing -- 2ª definición de todosJustos: todosJustos :: Eq a => [Maybe a] -> Bool todosJustos = all isJust -- 2ª solución -- =========== sumaSiTodosJustos2 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos2 xs | todosJustos xs = Just (sum [fromJust x | x <- xs]) | otherwise = Nothing -- 3ª solución -- =========== sumaSiTodosJustos3 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos3 xs | todosJustos xs = Just (sum (map fromJust xs)) | otherwise = Nothing -- 4ª solución sumaSiTodosJustos4 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos4 xs | todosJustos xs = Just (sum (catMaybes xs)) | otherwise = Nothing -- 5ª solución -- =========== sumaSiTodosJustos5 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos5 xs = suma (sequence xs) where suma Nothing = Nothing suma (Just ys) = Just (sum ys) -- Nota. En la solución anterior se usa la función -- sequence :: Monad m => [m a] -> m [a] -- tal que (sequence xs) es la mónada obtenida evaluando cada una de las -- de xs de izquierda a derecha. Por ejemplo, -- sequence [Just 2, Just 5] == Just [2,5] -- sequence [Just 2, Nothing] == Nothing -- sequence [[2,4],[5,7]] == [[2,5],[2,7],[4,5],[4,7]] -- sequence [[2,4],[5,7],[6]] == [[2,5,6],[2,7,6],[4,5,6],[4,7,6]] -- sequence [[2,4],[5,7],[]] == [] -- 6ª solución -- =========== sumaSiTodosJustos6 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos6 xs = fmap sum (sequence xs) -- 7ª solución -- =========== sumaSiTodosJustos7 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos7 = fmap sum . sequence -- Equivalencia de las definiciones -- ================================ -- La propiedad es prop_sumaSiTodosJustos :: [Maybe Integer] -> Bool prop_sumaSiTodosJustos xs = all (== sumaSiTodosJustos1 xs) [sumaSiTodosJustos2 xs, sumaSiTodosJustos3 xs, sumaSiTodosJustos4 xs, sumaSiTodosJustos5 xs, sumaSiTodosJustos6 xs, sumaSiTodosJustos7 xs] verifica_sumaSiTodosJustos :: IO () verifica_sumaSiTodosJustos = quickCheck prop_sumaSiTodosJustos -- La comprobación es -- λ> verifica_sumaSiTodosJustos -- +++ OK, passed 100 tests. |
El código se encuentra en GitHub.