【问题标题】:Haskell Insert function for Binary Trees用于二叉树的 Haskell 插入函数
【发布时间】:2019-04-08 07:20:08
【问题描述】:

我正在尝试创建一个名为“insertm”的函数,该函数应该将键和值插入二叉树。如果键已经存在,它应该返回“无”。如果不是,它应该根据它的值将键和值插入到树中。我能够完成大部分工作,但是我遇到了一个错误,我不确定如何修复。

这是一个例子:

      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)
                                          ^^^^^^^^^^^^^^^^

我也收到了我的其他情况的错误。所以我有点卡住任何帮助将不胜感激。

【问题讨论】:

    标签: haskell recursion binary-tree


    【解决方案1】:

    问题是(insertm x y left)Maybe (BinaryTree a b) in:

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

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

    但是,您可以“解压”该值,然后使用它,例如:

    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 =&gt; (a -&gt; b) -&gt; f a -&gt; f b,将Just x中的x映射到Just (f x),并将Nothing映射到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)

    或喜欢@JonPurdy 说:

    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

    (&lt;$&gt;) 是等价于fmap 的函数,(&lt;*&gt;) :: f (a -&gt; b) -&gt; f a -&gt; f b 是一个函数,它在此处接受 Maybe (BinaryTree a b -&gt; BinaryTree a b),并应用包装在 Just 中的函数 f,其值为 @ 987654345@ 包裹在右边的 Just 中并返回 Just (f x),因为这两个是 Justs,如果两者之一是 Nothing(或两者),那么它将返回 Nothing

    【讨论】:

    • flip 可以通过 Applicative 避免:Node val key &lt;$&gt; insertm x y left &lt;*&gt; pure rightliftA2 (Node val key) (insertm x y left) (pure right)(在这种情况下,pure = Just
    • 这太酷了!我研究 Haskell 已经有一段时间了,但我仍然不熟悉所有的技巧。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多