-- -- -- data Abn = EmptyAbn | LeafAbn Int | NodeAbn Int Abn Abn deriving(Show) data Abf = EmptyAbf | LeafAbf (Int -> Int) | NodeAbf (Int -> Int) Abf Abf anAbn1 = NodeAbn 5 (LeafAbn 4) (NodeAbn 3 EmptyAbn (LeafAbn 6)) anAbn2 = NodeAbn 5 (LeafAbn 4) (NodeAbn 3 EmptyAbn EmptyAbn) inc x = x+1 double x = x+x square x = x*x anAbf = NodeAbf inc (LeafAbf double) (NodeAbf square EmptyAbf (LeafAbf inc)) appT :: Abf -> Abn -> Abn appT EmptyAbf EmptyAbn = EmptyAbn appT (LeafAbf f) (LeafAbn n) = LeafAbn (f n) appT (NodeAbf f abf1 abf2) (NodeAbn n abn1 abn2) = (NodeAbn (f n) (appT abf1 abn1) (appT abf2 abn2)) -------------------- -- senza uso di >>= pappT :: Abf -> Abn -> (Maybe Abn) pappT EmptyAbf EmptyAbn = (Just EmptyAbn) pappT (LeafAbf f) (LeafAbn n) = (Just (LeafAbn (f n))) pappT (NodeAbf f abf1 abf2) (NodeAbn n abn1 abn2) = case (pappT abf1 abn1) of Nothing -> Nothing Just t1 -> case (pappT abf2 abn2) of Nothing -> Nothing Just t2 -> (Just (NodeAbn (f n) t1 t2)) pappT _ _ = Nothing partialAppT :: ---------------------- -- -- con uso di >>= -- prima di vedere la soluzione che usa >>= -- osserviamo che Abn e Abf in realta' potrebbero essere istanze -- del seguente tipo parametrico data AbL a = EmptyAbL | LeafAbL a | NodeAbL a (AbL a) (AbL a) deriving(Show) type Abn = AbL Integer type Abf = AbL (Integer -> Integer) -- ovviamente gli alberi che avevamo definito per usarli -- come test vanno ridefiniti anAbn3 = (NodeAbL 5 (LeafAbL 4) (NodeAbL 3 EmptyAbL (LeafAbL 6))) anAbn4 = (NodeAbL 5 (LeafAbL 4) (NodeAbL 3 EmptyAbL EmptyAbL)) anAbf2 = NodeAbL inc (LeafAbL double) (NodeAbL square EmptyAbL (LeafAbL inc)) -- definiamo ora la nostra funzione pappT1 :: Abf -> Abn -> (Maybe Abn) pappT1 EmptyAbL EmptyAbL = (Just EmptyAbL) pappT1 (LeafAbL f) (LeafAbL n) = (Just (LeafAbL (f n))) pappT1 (NodeAbL f abf1 abf2) (NodeAbL n abn1 abn2) = pappT1 abf1 abn1 >>= \t1 -> (pappT1 abf2 abn2) >>= \t2 -> Just (NodeAbL (f n) t1 t2) pappT1 _ _ = Nothing -- notiamo come sia possibile utilizzare la notazione "do" -- per ottenere un codice piu' leggibile pappT :: Abf -> Abn -> (Maybe Abn) pappT EmptyAbL EmptyAbL = (Just EmptyAbL) pappT (LeafAbL f) (LeafAbL n) = (Just (LeafAbL (f n))) pappT (NodeAbL f abf1 abf2) (NodeAbL n abn1 abn2) = do t1 <- pappT abf1 abn1 t2 <- pappT abf2 abn2 Just (NodeAbL (f n) t1 t2) pappT _ _ = Nothing