zipWith for trees in Haskell

前端 未结 1 485
生来不讨喜
生来不讨喜 2021-01-06 21:44

I am learning Haskell using The Haskell School of Expression: Learning Functional Programming through Multimedia and I am unsure how to go about solving this exercise.

相关标签:
1条回答
  • 2021-01-06 22:10

    First of all I believe your solution is not elegant because you are using undefined. You want to avoid partial functions, and structures, as much as possible and simply inserting some Node undefined undefined in a tree structure doesn't sound like a good idea.

    Think about this: once you have a Node undefined undefined how would it act with the other operations on the tree? You'd probably get tons of exceptions.

    So you have to find an alternative.

    zipTree (Node l r) (Leaf a) = Node x y
        where
            x = ... ? 
            y = ... ? 
    

    Now how should x and y be defined? x should depend on l and Leaf a while y should depend on r and Leaf a.

    The easiest way to define this case is to simply perform the recursive calls:

    zipTree (Node l r) a@(Leaf _) = Node (zipTree l a) (zipTree r a)
    

    So we are zipping all leafs in the l and r subtrees with the leaf a.

    As for the zipWithTree: that's easy. You have to add an f parameter and use f x y instead of (x, y) when you perform the zipping, which is done only in the Leaf v Leaf case:

    zipWithTree f (Leaf a) (Leaf b) = Leaf $ f a b
    

    Obviously you have to add the f parameter to all the rules and pass f to recursive calls.


    Note that there is also an other way to define zipWith, which is:

    zipTree (Node _ _) (Leaf a) = Leaf (undefined, a)
    

    This still isn't a good solution because it introduces an undefined however it has some advantages against the Node undefined undefined solution:

    1. It acts for similarly to zip from lists. zip [1,2] [1,2,3,4] == [(1,1), (2,2)] so you stop when the shorter list ends.

    2. The undefined is inside the value. This allows for example to have:

      mapTree snd (zipTree x y) == y
      

      whenever x has longer branches. Using Node undefined undefined you have mapTree f (zipTree x y) is always an exception whenever the trees aren't isomorphic (because mapTree will try to evaluate undefined).

    0 讨论(0)
提交回复
热议问题