{"id":7670,"date":"2022-03-08T17:18:13","date_gmt":"2022-03-08T16:18:13","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=7670"},"modified":"2022-03-12T07:46:22","modified_gmt":"2022-03-12T06:46:22","slug":"ejercicios-sobre-transacciones-en-haskell","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/ejercicios-sobre-transacciones-en-haskell\/","title":{"rendered":"PFH: Ejercicios sobre transacciones en Haskell"},"content":{"rendered":"<p>He a\u00f1adido a la colecci\u00f3n de <a href=\"https:\/\/bit.ly\/3CeabJd\">Ejercicios de programaci\u00f3n funcional con Haskell<\/a><br \/>\nla relaci\u00f3n <a href=\"https:\/\/bit.ly\/3HMUxWg\">Transacciones<\/a> en la que se estudia las transacciones de las cadenas<br \/>\nde bloques (en ingl\u00e9s, &#8220;blockchain&#8221;) que estudiamos en <a href=\"https:\/\/bit.ly\/3trXIgW\">Cadenas de bloques<\/a>.<\/p>\n<p>El contenido de la relaci\u00f3n es el siguiente<br \/>\n<!--more--><\/p>\n<pre lang=\"haskell\">\nmodule Transacciones where\n\nimport Data.Maybe (fromMaybe)\nimport Prelude    hiding (lookup)\nimport Data.Map   (Map, alter, findWithDefault, insert, lookup)\nimport Test.QuickCheck\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 1. Definir el tipo Importe para representar el importe de\n-- las transacciones como sin\u00f3nimo de Int.\n-- ---------------------------------------------------------------------\n\ntype Importe  = Int\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 2. Definir el tipo Cuenta para representar las cuentas de\n-- las transacciones como sin\u00f3nimo de String.\n-- ---------------------------------------------------------------------\n\ntype Cuenta = String\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 3. Definir el tipo de dato Transaccion con tres\n-- constructores:\n-- + trImporte con el importe de la transacci\u00f3n,\n-- + trDe con la cuenta del emisor y\n-- + trA con la cuenta del receptor.\n-- ---------------------------------------------------------------------\n\ndata Transaccion = Transaccion { trImporte :: Importe\n                               , trDe      :: Cuenta\n                               , trA       :: Cuenta\n                               }\n  deriving (Eq, Show)\n\n-- En los ejemplos se usar\u00e1n las siguientes transacciones:\ntransaccion1, transaccion2 :: Transaccion\ntransaccion1 = Transaccion 10 \"Ana\" \"Luis\"\ntransaccion2 = Transaccion { trImporte = 7\n                           , trDe      = \"Luis\"\n                           , trA       = \"Abel\"\n                           }\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 4. Definir el procedimiento\n--    transaccionArbitraria :: Gen Transaccion\n-- tal que transiccionArbitraria es una transicci\u00f3n aleatoria. Por\n-- ejemplo,\n--    \u03bb> sample transaccionArbitraria\n--    Transaccion {trImporte = 0, trDe = \"adefklmnopqvw\", trA = \"adgiklnoqstuw\"}\n--    Transaccion {trImporte = 0, trDe = \"abcdehjmopqruwxz\", trA = \"abcfgkmoqrtvwx\"}\n--    Transaccion {trImporte = 0, trDe = \"acdegjklprtvw\", trA = \"abdefghijklnoptvx\"}\n--    Transaccion {trImporte = 6, trDe = \"aefhjklnoqxz\", trA = \"abfikmosvwx\"}\n--    Transaccion {trImporte = -1, trDe = \"bdfghjklnuvwxy\", trA = \"begjklmruv\"}\n--    Transaccion {trImporte = -4, trDe = \"abcdiklnprsux\", trA = \"acdghijklnoprsxz\"}\n--    Transaccion {trImporte = 3, trDe = \"cijoprstux\", trA = \"bdfmnoqrsuxy\"}\n--    Transaccion {trImporte = 5, trDe = \"cdhijlnqruv\", trA = \"ceghijklmortwxy\"}\n--    Transaccion {trImporte = 9, trDe = \"cdfhijlrtuwxyz\", trA = \"abcdegijlptuw\"}\n--    Transaccion {trImporte = 0, trDe = \"cdefgijkmnpstuy\", trA = \"bcdfpqrtuwyz\"}\n--    Transaccion {trImporte = -17, trDe = \"chklmnqsuvw\", trA = \"adhilmnopqrwxy\"}\n-- ---------------------------------------------------------------------\n\ntransaccionArbitraria :: Gen Transaccion\ntransaccionArbitraria = do\n  i <- arbitrary\n  d <- sublistOf ['a'..'z']\n  a <- sublistOf ['a'..'z']\n  return (Transaccion i d a)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 5. Declarar Transiccion como subclase de Arbitraria usando\n-- el generador transiccionArbitraria.\n-- ---------------------------------------------------------------------\n\ninstance Arbitrary Transaccion where\n  arbitrary = transaccionArbitraria\n  shrink (Transaccion a f t) = [Transaccion a' f  t  | a' <- shrink a] ++\n                               [Transaccion a  f' t  | f' <- shrink f] ++\n                               [Transaccion a  f  t' | t' <- shrink t]\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 6. Definir la funci\u00f3n\n--    inversa :: Transaccion -> Transaccion\n\n-- tal que (inversa t) es la transicci\u00f3n cuyo importe y direcci\u00f3n son\n-- opuestos a los de t. Por ejemplo,\n--    \u03bb> inversa (Transaccion {trImporte = 10, trDe = \"Ana\", trA = \"Luis\"})\n--    Transaccion {trImporte = -10, trDe = \"Luis\", trA = \"Ana\"}\n-- ---------------------------------------------------------------------\n\ninversa :: Transaccion -> Transaccion\ninversa t = Transaccion { trImporte = - (trImporte t)\n                        , trDe      = trA t\n                        , trA       = trDe t\n                        }\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 7. Comprobar con QuickCheck que la funci\u00f3n inversa es\n-- involutiva.\n-- ---------------------------------------------------------------------\n\n-- La propiedad es\nprop_inversa_inversa :: Transaccion -> Property\nprop_inversa_inversa t = inversa (inversa t) === t\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_inversa_inversa\n--    +++ OK, passed 100 tests.\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 8. Definir la funci\u00f3n\n--    normalizada :: Transaccion -> Transaccion\n-- tal que (normalizada t) es la inversa de t, si el importe de t es\n-- negativo y es t, en caso contrario. Por ejemplo,\n--    \u03bb> normalizada (Transaccion {trImporte = -5, trDe = \"Ana\", trA = \"Luis\"})\n--    Transaccion {trImporte = 5, trDe = \"Luis\", trA = \"Ana\"}\n--    \u03bb> normalizada (Transaccion {trImporte = 7, trDe = \"Ana\", trA = \"Luis\"})\n--    Transaccion {trImporte = 7, trDe = \"Ana\", trA = \"Luis\"}\n-- ---------------------------------------------------------------------\n\nnormalizada :: Transaccion -> Transaccion\nnormalizada t\n  | trImporte t < 0 = inversa t\n  | otherwise       = t\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 9. Comprobar con QuickCheck que la funci\u00f3n normalizada es\n-- idempotente.\n-- ---------------------------------------------------------------------\n\n-- La propiedad es\nprop_normalizada_normalizada :: Transaccion -> Property\nprop_normalizada_normalizada t =\n  normalizada (normalizada t) === normalizada t\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_normalizada_normalizada\n--    +++ OK, passed 100 tests.\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 10. Comprobar con QuickCheck que el importe de las\n-- transacciones normalizadas son no negativos.\n-- ---------------------------------------------------------------------\n\n-- La propiedad es\nprop_normalizada_no_negativa :: Transaccion -> Bool\nprop_normalizada_no_negativa t =\n  trImporte (normalizada t) >= 0\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_normalizada_no_negativa\n--    +++ OK, passed 100 tests.\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 11. Definir el tipo Cuentas como sin\u00f3nimo de los\n-- diccionarios con claves de tipo Cuenta y valores de tipo Importe.\n-- ---------------------------------------------------------------------\n\ntype Cuentas = Map Cuenta Importe\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 12. Definir la funci\u00f3n\n--    procesaTransaccion :: Transaccion -> Cuentas -> Cuentas\n-- tal que (procesaTransaccion t cs) es el estado de las cuentas\n-- obtenido despu\u00e9s de aplicar la transacci\u00f3n t a cs. Por ejemplo,\n--    \u03bb> procesaTransaccion (Transaccion 60 \"Ana\" \"Bea\") (fromList [(\"Ana\",90)])\n--    fromList [(\"Ana\",30),(\"Bea\",60)]\n--    \u03bb> procesaTransaccion (Transaccion 40 \"Bea\" \"Ana\") it\n--    fromList [(\"Ana\",70),(\"Bea\",20)]\n--    \u03bb> procesaTransaccion (Transaccion 40 \"Bea\" \"Eva\") it\n--    fromList [(\"Ana\",70),(\"Bea\",-20),(\"Eva\",40)]\n-- ---------------------------------------------------------------------\n\n-- 1\u00aa definici\u00f3n\nprocesaTransaccion :: Transaccion -> Cuentas -> Cuentas\nprocesaTransaccion (Transaccion i d a) cs =\n  insert d (sd - i) (insert a (sa + i) cs)\n  where sd = fromMaybe 0 (lookup d cs)\n        sa = fromMaybe 0 (lookup a cs)\n\n-- 2\u00aa definici\u00f3n\nprocesaTransaccion2 :: Transaccion -> Cuentas -> Cuentas\nprocesaTransaccion2 (Transaccion i d a) cs =\n  insert d (sd - i) (insert a (sa + i) cs)\n  where sd = findWithDefault 0 d cs\n        sa = findWithDefault 0 a cs\n\n-- 3\u00aa definici\u00f3n\nprocesaTransaccion3 :: Transaccion -> Cuentas -> Cuentas\nprocesaTransaccion3 t =\n  alter (add (- x)) (trDe t) .\n  alter (add    x ) (trA  t)\n  where x = trImporte t\n        add a Nothing  = Just a\n        add a (Just b) = Just (a + b)\n\n-- Propiedad de equivalencia de las definiciones\nprop_procesaTransaccion :: Transaccion -> Cuentas -> Bool\nprop_procesaTransaccion t cs =\n  all (== procesaTransaccion t cs)\n      [procesaTransaccion2 t cs,\n       procesaTransaccion3 t cs]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_procesaTransaccion\n--    +++ OK, passed 100 tests.\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 13. Definir la funci\u00f3n\n--    procesaTransacciones :: [Transaccion] -> Cuentas -> Cuentas\n-- tal que (procesaTransacciones ts cs) es el estado de las cuentas\n-- obtenido despu\u00e9s de aplicar las transacciones ts a cs. Por ejemplo,\n--    \u03bb> t1 = Transaccion 60 \"Ana\" \"Bea\"\n--    \u03bb> t2 = Transaccion 40 \"Bea\" \"Ana\"\n--    \u03bb> t3 = Transaccion 40 \"Bea\" \"Eva\"\n--    \u03bb> procesaTransacciones [t1,t2,t3] (fromList [(\"Ana\",90)])\n--    fromList [(\"Ana\",70),(\"Bea\",-20),(\"Eva\",40)]\n-- ---------------------------------------------------------------------\n\nprocesaTransacciones :: [Transaccion] -> Cuentas -> Cuentas\nprocesaTransacciones []       cs = cs\nprocesaTransacciones (t : ts) cs =\n  procesaTransacciones ts (procesaTransaccion t cs)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 14. Definir la funci\u00f3n\n--    procesaTransaccion' :: Transaccion -> Cuentas -> Maybe Cuentas\n-- tal que (procesaTransaccion' t cs) es el estado de las cuentas\n-- obtenido despu\u00e9s de aplicar la transacci\u00f3n t a cs si no resulta\n-- ning\u00fan saldo negativo y Nothing, en caso contrario. Por ejemplo,\n--    \u03bb> procesaTransaccion' (Transaccion 80 \"Ana\" \"Bea\") (fromList [(\"Ana\",70)])\n--    Nothing\n--    \u03bb> procesaTransaccion' (Transaccion 60 \"Ana\" \"Bea\") (fromList [(\"Ana\",70)])\n--    Just (fromList [(\"Ana\",10),(\"Bea\",60)])\n--    \u03bb> procesaTransaccion' (Transaccion 70 \"Bea\" \"Ana\") (fromList [(\"Ana\",10),(\"Bea\",60)])\n--    Nothing\n--    \u03bb> procesaTransaccion' (Transaccion 40 \"Bea\" \"Ana\") (fromList [(\"Ana\",10),(\"Bea\",60)])\n--    Just (fromList [(\"Ana\",50),(\"Bea\",20)])\n-- ---------------------------------------------------------------------\n\nprocesaTransaccion' :: Transaccion -> Cuentas -> Maybe Cuentas\nprocesaTransaccion' (Transaccion i d a) cs\n  | sd2 < 0 || sa2 < 0 = Nothing\n  | otherwise          = Just (insert d sd2 (insert a sa2 cs))\n  where sd1 = findWithDefault 0 d cs\n        sa1 = findWithDefault 0 a cs\n        sd2 = sd1 - i\n        sa2 = sa1 + i\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 15. Definir la funci\u00f3n\n--    procesaTransacciones' :: [Transaccion] -> Cuentas -> Maybe Cuentas\n-- tal que (procesaTransacciones' ts cs) es el estado de las cuentas\n-- obtenido despu\u00e9s de aplicar las transacciones ts a cs, si en el\n-- proceso no hay saldos negativos y es Nothing, en caso contrario. Por\n-- ejemplo,\n--    \u03bb> t1 = Transaccion 60 \"Ana\" \"Bea\"\n--    \u03bb> t2 = Transaccion 40 \"Bea\" \"Ana\"\n--    \u03bb> t3 = Transaccion 40 \"Bea\" \"Eva\"\n--    \u03bb> procesaTransacciones' [t1,t2] (fromList [(\"Ana\",90)])\n--    Just (fromList [(\"Ana\",70),(\"Bea\",20)])\n--    \u03bb> procesaTransacciones' [t1,t2,t3] (fromList [(\"Ana\",90)])\n--    Nothing\n-- ---------------------------------------------------------------------\n\n-- 1\u00aa definici\u00f3n\nprocesaTransacciones' :: [Transaccion] -> Cuentas -> Maybe Cuentas\nprocesaTransacciones' []       cs = Just cs\nprocesaTransacciones' (t : ts) cs =\n  case procesaTransaccion' t cs of\n    Nothing  -> Nothing\n    Just cs' -> procesaTransacciones' ts cs'\n\n\n-- 2\u00aa definici\u00f3n\nprocesaTransacciones'' :: [Transaccion] -> Cuentas -> Maybe Cuentas\nprocesaTransacciones'' []       cs = Just cs\nprocesaTransacciones'' (t : ts) cs =\n  procesaTransaccion' t cs >>= procesaTransacciones'' ts\n\n-- ---------------------------------------------------------------------\n-- \u00a7 Referencias                                                      --\n-- ---------------------------------------------------------------------\n\n-- Esta relaci\u00f3n de ejercicios es una adaptaci\u00f3n de\n-- \"Transactions.hs\" https:\/\/bit.ly\/3tBxSar de Lars Br\u00fcnjes.\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>He a\u00f1adido a la colecci\u00f3n de Ejercicios de programaci\u00f3n funcional con Haskell la relaci\u00f3n Transacciones en la que se estudia las transacciones de las cadenas de bloques (en ingl\u00e9s, &#8220;blockchain&#8221;) que estudiamos en Cadenas de bloques. El contenido de la relaci\u00f3n es el siguiente<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false},"categories":[337],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7670"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/comments?post=7670"}],"version-history":[{"count":3,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7670\/revisions"}],"predecessor-version":[{"id":7686,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7670\/revisions\/7686"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=7670"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=7670"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=7670"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}