二叉树的Haskell插入函数

时间:2018-11-04 21:47:23

标签: haskell recursion binary-tree

我正在尝试创建一个名为“ insertm”的函数,该函数应该将键和值插入二叉树。如果键已经存在,则应返回“ nothing”。如果不是,则应根据其值将键和值插入树中。我能够解决其中的大部分问题,但是却遇到一个错误,我不确定该如何解决。

这里是一个例子:

      TestQ4> insertm 25 "vw" t5
      Just (10:"ghi")<$,(30:"def")<(20:"abc")<$,(25:"vw")>,$>>
      TestQ4> insertm 20 "vw" t5
      Nothing

这是我的代码:

     data BinaryTree a b = Leaf | Node a b (BinaryTree a b) (BinaryTree a b) 

     insertm :: (Ord a, Show a, Show b) =>
     a -> b -> BinaryTree a b -> Maybe (BinaryTree a b)

     insertm val key Leaf = Just (Node val key Leaf Leaf)
     insertm x y (Node val key left right)
          | x == val = Nothing
          | x < val = Just (Node val key (insertm x y left) right)
          | otherwise = Just (Node val key left (insertm x y right))

这是我得到的错误:

       * Couldn't match expected type `BinaryTree a b'
              with actual type `Maybe (BinaryTree a b)'
       * In the fourth argument of `Node', namely `(insertm x y right)'
         In the first argument of `Just', namely
           `(Node val key left (insertm x y right))'
         In the expression: Just (Node val key left (insertm x y right))
       * Relevant bindings include
          right :: BinaryTree a b (bound at TestQ4.hs:101:32)
          left :: BinaryTree a b (bound at TestQ4.hs:101:27)
          key :: b (bound at TestQ4.hs:101:23)
          val :: a (bound at TestQ4.hs:101:19)
          y :: b (bound at TestQ4.hs:101:11)
          x :: a (bound at TestQ4.hs:101:9)
         (Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max- 
            relevant-binds)

          | x < val = Just (Node val key (insertm x y left) right)
                                          ^^^^^^^^^^^^^^^^

在其他情况下,我也会收到错误消息。因此,我有点停滞不前,我们将不胜感激。

1 个答案:

答案 0 :(得分:3)

问题在于(insertm x y left)在以下位置是Maybe (BinaryTree a b)

 | x < val = Just (Node val key (insertm x y left) right)

不是BinaryTree a b,因此,您不能仅仅以BinaryTree作为子树来构造这样的Maybe (BinaryTree a b)

不过,您可以“解包”值,然后使用它,例如:

insertm :: (Ord a, Show a, Show b) => a -> b -> BinaryTree a b -> Maybe (BinaryTree a b)
insertm val key Leaf = Just (Node val key Leaf Leaf)
insertm x y (Node val key left right)
    | x == val = Nothing
    | x < val = case insertm x y left of
        Just l -> Just (Node val key l right)
        Nothing -> Nothing
    | otherwise =  case insertm x y right of
        Just r -> Just (Node val key left r)
        Nothing -> Nothing

上述模式非常流行,我们可以在此处使用fmap :: Functor f => (a -> b) -> f a -> f b,将x中的Just x映射到Just (f x)并在{ {1}}:

Nothing

或像@JonPurdy这样说:

Nothing

insertm :: (Ord a, Show a, Show b) => a -> b -> BinaryTree a b -> Maybe (BinaryTree a b) insertm val key Leaf = Just (Node val key Leaf Leaf) insertm x y (Node val key left right) | x == val = Nothing | x < val = fmap (flip (Node val key) right) (insertm x y left) | otherwise = fmap (Node val key left) (insertm x y right)是等效于insertm :: (Ord a, Show a, Show b) => a -> b -> BinaryTree a b -> Maybe (BinaryTree a b) insertm val key Leaf = Just (Node val key Leaf Leaf) insertm x y (Node val key left right) | x == val = Nothing | x < val = Node val key <$> insertm x y left <*> pure right | otherwise = Node val key left <$> insertm x y right的函数,而(<*>) :: f (a -> b) -> f a -> f b是在此处使用(<$>)并应用函数fmap的函数。如果值Maybe (BinaryTree a b -> BinaryTree a b)包裹在f中,并且值Just包裹在右边的x中,则返回值Just,如果两个是Just (f x),则如果两者之一Just(或同时包含两者),则它将返回Nothing