首页 > 解决方案 > 我应该如何正确传递列表参数?通过这种方式,解释器给了我预期类型的​​错误

问题描述

我想在树列表中找到具有最大子节点数的节点。

我尝试将参数传递为 't' ,作为单例 '[t]',作为模式匹配 '(t:ts)',作为 '[Tree t]'。以上都没有奏效。

data Tree a = Void2 | Node2 a [Tree a] deriving (Eq,Show)


degree [Void2] = 0
degree [] = 0
degree (Node2 a t) = max (length t) (maximum (map degree t))

这是口译员给我的错误

Couldn't match expected type ‘[Tree a0]’
                  with actual type ‘Tree a’
    • In the pattern: Node2 a t
      In an equation for ‘degree’:
          degree (Node2 a t) = max (length t) (maximum (map degree t))
    • Relevant bindings include
        degree :: Tree a -> Int (bound at Esercizi_Haskell.hs:67:1)
   |
   | degree (Node2 a t) = max (length t) (maximum (map degree t))

标签: haskellarguments

解决方案


degree用 type定义函数似乎没有多大意义degree :: [Tree a] -> Int。如果我查询树列表的度数,我希望得到一个数字列表。特别是因为该列表可以包含许多不同的树,这些树不是较大树的子树。

degree :: Tree a -> Int定义一个函数来计算特定树的度数更有意义。因此,我们可以将其实现为:

degree :: Tree a -> Int
degree Void2 = 0
degree (Node2 _ t) = max (length t) (maximum (map degree t))

然而,它在这里包含一个问题:如果Node2没有孩子,则,map degree t将返回一个空列表,并且maximum :: Ord a => [a] -> a在一个空列表上会引发错误。但是,我们可以将其length t作为元素之一传递,例如:

degree :: Tree a -> Int
degree Void2 = 0
degree (Node2 _ t) = maximum (length t : map degree t)

因此,我们在这里消除了代码中的列表输入以及第二个子句,因为空列表没有树 itef 的对应项。以上确实是一种计算度数的方法。

我们可以在这里使用下划线 ( _) 作为数据构造函数的第一个参数Node2,因为我们对节点本身的值感兴趣。

我们还可以将更多逻辑放在另一个函数children :: Tree a -> [Tree a]中,例如:

children :: Tree a -> [Tree a]
children Void2 = []
children (Node2 _ t) = t

在这种情况下,我们可以degree简单地定义为:

import Control.Applicative(liftA2)

degree :: Tree a -> Int
degree = maximum . liftA2 (:) length (map degree) . children

推荐阅读