【问题标题】:A Haskell Problem writing Error Found hole _ a5一个 Haskell 写错误的问题 Found hole _ a5
【发布时间】:2019-12-04 18:47:37
【问题描述】:

创建一个计算二叉树中下一个元素的函数。

data BSearchTree a = Nil | Node a (BSearchTree a) (BSearchTree a)
                      deriving (Show, Eq)
successor :: (Ord a) => a -> BSearchTree a -> Maybe a 
successor a = if a Nil then Just succ Nil
              else if a (Node _ t1 t2)
               then Just succ a (Node _ t1 t2)
           else Nothing

找到的洞:_ :: a5 其中:‘a5’是一个模棱两可的类型变量 • 在‘Node’的第一个参数中,即‘_’ 在‘a’的第一个参数中,即‘(Node_t1 t2)’ 在表达式中:a (Node_t1 t2) • 相关绑定包括 a :: a (绑定在桌面/Aufgabe6.4.hs:32:11) 继任者 :: a -> BSearchTree a -> Maybe a (绑定在桌面/Aufgabe6.4.hs:32:1) 约束包括 Ord a(来自 desktop/Aufgabe6.4.hs:30:1-53) | | else if a (Node_t1 t2)

不太明白,错误是什么意思……

【问题讨论】:

  • 下划线 (_) 表示它仍然是您需要填写的内容。孔有时用于让 Haskell 导出该孔的类型(并给出部分解决方案:))跨度>
  • 您正在尝试使用if 进行模式匹配,但if 不进行模式匹配。您需要使用case a of .... 或多个定义方程。

标签: haskell binary-tree binary-search-tree


【解决方案1】:

在您的代码中,successor 函数右侧有两个下划线(_),它们是typed holes [haskell-wiki]

类型化的孔对于让编译器生成应该放置在那里的项目的类型很有用,如果你自己很难弄清楚的话。在诸如 StackOverflow 之类的 QA 站点上,类型化漏洞经常用于提供 OP 仍需要实现某些方面的解决方案。

在这种特定情况下,您需要在两个子表达式(Node _ t1 t2) 中为_ 填写一些表达式(这两种情况下的表达式本身不同相同)。

【讨论】:

  • 我认为没有任何东西可以填补这些漏洞以使程序编译。无论您为它构造什么参数,将 a 作为函数调用都是没有意义的。
【解决方案2】:
if a (Node _ t1 t2)

这不是有效的 Haskell。您似乎将if 视为进行模式匹配的地方,而实际上它需要一个布尔表达式。

if a Nil then

这似乎遵循相同的逻辑。

请考虑通过 case 表达式或函数定义进行模式匹配:

successor :: (Ord a) => a -> BSearchTree a -> Maybe a 
successor _NotUsingThisValue Nil = ... something ...
successor valToMatch (Node val leftTree rightTree) = .. other thing ..

注意Just succ Nil 也无效。首先,它解析为(Just succ) Nil(不是Just (succ Nil)),其次这里没有有意义地使用succ

【讨论】:

    【解决方案3】:

    在 Haskell 中,if 语句适用于 Bool 值。在您的程序中,您的语法类似于if (a Nil) then ... else ...。不幸的是,(a Nil) 不是Bool 值。事实上,a Nil 根本不是一个类型良好的值。

    因此,编写代码的一种方式是 Thomas M. DuBuisson 所说的方式。另一种方法是使用case ... of ... 语法。

    successor :: (Ord a) => a -> BSearchTree a -> Maybe a 
    successor a = case a of
                    Nil -> Just (succ Nil)
                    n@(Node _ t1 t2) -> Just (succ a n)
                    _ -> Nothing
    

    其他几个cmets:

    • 注意上面n@(Node _ t1 t2) 的使用。这表示“记住任何与此模式匹配的内容为n”。将Just (succ a (Node _ t1 t2)) 写在模式的右侧是行不通的,因为(Node _ t1 t2) 是一个模式,而不是一个值,也就是说,它是一条指令来匹配那个“形状”的BSearchTree a 值。
    • BSearchTree a 类型的每个值始终与 NilNode _ _ _ 匹配。这是由 Haskell 语义保证的。因此,您实际上并不需要 else Nothing 分支。
    • 您可以将case a of Nil -> ... ; _ -> ... 写成if (a == Nil) then ... else ...,但这是不可取的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-18
      • 2016-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      相关资源
      最近更新 更多