Ir al contenido principal

Valor de expresiones aritméticas generales

Las operaciones de suma, resta y multiplicación se pueden representar mediante el siguiente tipo de datos

   data Op = S | R | M

La expresiones aritméticas con dichas operaciones se pueden representar mediante el siguiente tipo de dato algebraico

   data Expr = C Int
             | A Op Expr Expr

Por ejemplo, la expresión

   (7-3)+(2*5)

se representa por

   A S (A R (C 7) (C 3)) (A M (C 2) (C 5))

Definir la función

   valor :: Expr -> Int

tal que valor e es el valor de la expresión e. Por ejemplo,

   valor (A S (A R (C 7) (C 3)) (A M (C 2) (C 5)))  ==  14
   valor (A M (A R (C 7) (C 3)) (A S (C 2) (C 5)))  ==  28

Soluciones

A continuación se muestran las soluciones en Haskell y las soluciones en Python.

Soluciones en Haskell

data Op = S | R | M

data Expr = C Int
          | A Op Expr Expr

-- 1ª solución
-- ===========

valor :: Expr -> Int
valor (C x)      = x
valor (A o e1 e2) = aplica o (valor e1) (valor e2)
  where aplica :: Op -> Int -> Int -> Int
        aplica S x y = x+y
        aplica R x y = x-y
        aplica M x y = x*y

-- 2ª solución
-- ===========

valor2 :: Expr -> Int
valor2 (C n)    = n
valor2 (A o x y) = sig o (valor2 x) (valor2 y)
  where sig :: Op -> Int -> Int -> Int
        sig S = (+)
        sig M = (*)
        sig R = (-)

Soluciones en Python

from dataclasses import dataclass
from enum import Enum

Op = Enum('Op', ['S', 'R', 'M'])

@dataclass
class Expr:
    pass

@dataclass
class C(Expr):
    x: int

@dataclass
class A(Expr):
    o: Op
    x: Expr
    y: Expr

def aplica(o: Op, x: int, y: int) -> int:
    match o:
        case Op.S:
            return x + y
        case Op.R:
            return x - y
        case Op.M:
            return x * y
    assert False

def valor(e: Expr) -> int:
    match e:
        case C(x):
            return x
        case A(o, e1, e2):
            return aplica(o, valor(e1), valor(e2))
    assert False