【问题标题】:Haskell algebraic data type pattern matchingHaskell 代数数据类型模式匹配
【发布时间】:2012-05-04 22:47:46
【问题描述】:

我有以下:

data Alpha a = Beta a [Alpha a]
val = Beta 1 [Beta 2 [], Beta 5 [Beta 7 []]]

我正在尝试定义一个函数,该函数将移动 Alpha Int 类型的 val 并将其求和。我想要的方法是提取所有 Int,然后对结果列表求和,但我正在努力提取所有 Int,因为我不知道如何处理递归......

轻微的尝试:

checkAlpha :: Alpha Int -> [Int]
checkAlpha (Beta a []) = [a]
checkAlpha (Beta a b) = [a] ++ (map checkAlpha b)

显然这不太有效,但我看不到解决方案。

【问题讨论】:

  • 在您的函数中,b 的类型为 [Alpha Int]。在此列表上映射checkAlpha 会得到[[Int]],但您的签名表明您想要返回[Int]。这就是为什么您必须将列表“折叠”成一层 - 即 (concat .) . map 也称为 concatMap
  • 最小的修复方法是在代码中的(map checkAlpha b) 之间插入concat $,以使列表列表变平一层。然后你注意到第一个子句是第二个子句的一个实例,因为map _ [] === []。然后将[a]++ 替换为a: 以得出Daniel 的解决方案。所以你真的很亲近。 :)

标签: haskell pattern-matching algebraic-data-types


【解决方案1】:

如果你用过

concatMap :: (a -> [b]) -> [a] -> [b]

代替map,它可以工作并且足够优雅。

您不需要将空列表的大小写为第二个组件,

checkAlpha :: Alpha a -> [a]
checkAlpha (Beta a alphas) = a : concatMap checkAlpha alphas

做你想做的事,并且与参数类型无关。

【讨论】:

    【解决方案2】:

    您可以考虑使用Tree 代替Alpha,它有很多方便的操作:

    > flatten $ Node 1 [Node 2 [], Node 5 [Node 7 []]]
    [1,2,5,7]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 1970-01-01
      相关资源
      最近更新 更多