-- | -- Module : Suma_si_todos_justos -- Description : Suma si todos los valores son justos. -- Copyright : Exercitium (01-05-14) -- License : GPL-3 -- Maintainer : JoseA.Alonso@gmail.com -- -- Definir la función -- -- > 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, -- -- >>> sumaSiTodosJustos [Just 2, Just 5] -- Just 7 -- >>> sumaSiTodosJustos [Just 2, Just 5, Nothing] -- Nothing module Suma_si_todos_justos ( sumaSiTodosJustos , verifica_sumaSiTodosJustos ) where import Data.Maybe import Test.QuickCheck -- | 1ª definición sumaSiTodosJustos :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos xs | todosJustos xs = Just (sum [x | (Just x) <- xs]) | otherwise = Nothing -- | (todosJustos xs) se verifica si todos los elementos de xs si todos -- 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: todosJustos :: Eq a => [Maybe a] -> Bool todosJustos = notElem Nothing -- | 2ª definición de todosJustos (con isJust): todosJustos2 :: Eq a => [Maybe a] -> Bool todosJustos2 = all isJust -- | 2ª definición de sumaSiTodosJustos (con fromJust): sumaSiTodosJustos2 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos2 xs | todosJustos xs = Just (sum [fromJust x | x <- xs]) | otherwise = Nothing -- 3ª definición de sumaSiTodosJustos (con catMaybes): sumaSiTodosJustos3 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos3 xs | todosJustos xs = Just (sum (catMaybes xs)) | otherwise = Nothing -- 4ª definición de sumaSiTodosJustos (con sequence): sumaSiTodosJustos4 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos4 xs = suma (sequence xs) where suma Nothing = Nothing suma (Just ys) = Just (sum ys) -- Nota. En la definició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],[]] == [] -- 5ª definición de sumaSiTodosJustos (con sequence y fmap): sumaSiTodosJustos5 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos5 xs = fmap sum (sequence xs) -- Nota. En la definición anterior se usa la función -- fmap :: (a -> b) -> f a -> f b -- tal que (fmap f x) aplica la función f al functor x. Por ejemplo, -- fmap (+2) (Just 3) == Just 5 -- fmap (+2) Nothing == Nothing -- fmap (+2) [3,7] == [5,9] -- fmap (+2) [] == [] -- 6ª definición de sumaSiTodosJustos (con sequence, fmap y (.)): sumaSiTodosJustos6 :: (Num a, Eq a) => [Maybe a] -> Maybe a sumaSiTodosJustos6 = fmap sum . sequence -- | Comprobación de la equivalencia de las definiciones de -- todosJustos. -- -- >>> prop_todosJustos [Just 2, Just 5] -- True -- >>> prop_todosJustos [Just 2, Just 5, Nothing] -- True -- >>> quickCheck prop_todosJustos -- +++ OK, passed 100 tests. prop_todosJustos :: [Maybe Int] -> Bool prop_todosJustos xs = todosJustos xs == todosJustos2 xs -- | Comprobación de la equivalencia de las definiciones de -- todosJustos. -- -- >>> prop_sumaSiTodosJustos [Just 2, Just 5] -- True -- >>> prop_sumaSiTodosJustos [Just 2, Just 5, Nothing] -- True -- >>> quickCheck prop_sumaSiTodosJustos -- +++ OK, passed 100 tests. prop_sumaSiTodosJustos :: [Maybe Int] -> Bool prop_sumaSiTodosJustos xs = all (== sumaSiTodosJustos xs) [f xs | f <- [ sumaSiTodosJustos2 , sumaSiTodosJustos3 , sumaSiTodosJustos4 , sumaSiTodosJustos5 , sumaSiTodosJustos6 ]] -- | Verificación verifica_sumaSiTodosJustos :: IO () verifica_sumaSiTodosJustos = do quickCheck prop_todosJustos quickCheck prop_sumaSiTodosJustos -- Comprobación -- > stack exec doctest src/Suma_si_todos_justos.hs -- Examples: 10 Tried: 10 Errors: 0 Failures: 0