在haskell中求立方

  • 本文关键字:立方 haskell haskell
  • 更新时间 :
  • 英文 :


Haskell有sum函数

sum :: Num a => [a] -> a

可以很好地组合成用

对矩阵求和
sum . map sum :: Num a => [[a]] -> a

更深入一些,比如对一个立方体求和,就会创建限制Num [a]

sum . map sum . map sum :: (Num a, Num [a]) => [[[a]]] -> a

仔细想想,这是很自然的。因此,由于前一种定义sumcube函数的尝试让人不知所措,我们需要找到另一条路径。一个这样的尝试是:

sum . map sum . map (map sum) :: Num a => [[[a]]] -> a

似乎没有什么比求和函数更自然的了。

在我寻求在Haskell中拥有解决问题的心理工具的过程中,我有兴趣知道如何解决这个问题,即通过堆叠map sum s来解决任何深度的结构求和的问题,就像我的第三个代码示例一样。这有可能吗?在这种情况下,你会怎么做?

类型类呢?

class Summable a where
  total :: a -> Int
instance Summable Int where
  total = id  
instance Summable x => Summable [x] where
  total = sum . map total  
total ([[[1,2,3],[4,5]],[[6],[7,8,9,10]]] :: [[[Int]]])
--55

你必须从内到外工作。当你有一个用于对数据结构求和的函数f时,那么sum . map f就是对这些数据结构列表求和的方法。

                     sum  :: Num a =>   [a]   -> a
           sum . map sum  :: Num a =>  [[a]]  -> a
sum . map (sum . map sum) :: Num a => [[[a]]] -> a

也许是这个?假设结合性,但添加新层很简单

 sum . concat . concat :: Num c => [[[c]]] -> c

根据前一个维度的sum来定义一个额外维度的sum,这对我来说是最自然的。

-- given sum :: Num a => [a] -> a
sum2 :: [[a]] -> a
sum2 = sum . map sum
sum3 :: [[[a]]] -> a
sum3 = sum . map sum2
sum4 :: [[[[a]]]] -> a
sum4 = sum . map sum3

这与Sjoerd所说的基本相同。如果你想只使用mapsum而不是,将常见的子表达式重构成有用的名称…然后使用等式推理来替换自定义函数sum2, sum3

首先,有模板Haskell (GHC扩展虽然)。或者你可以使用data,它支持任意深度列表嵌套,像这样:

data Tree a = Leaf a | Node [Tree a]
sumTree (Leaf x) = x
sumTree (Node xs) = (sum . map sumTree) xs
main = print $ sumTree $ Node [ Node [Leaf 3, Leaf 4, Leaf 5]
                              , Node [Leaf 1, Leaf 4, Leaf 2]]

将在这里打印19。然而,这并不能确保所有的叶子都有相同的嵌套深度,我不知道如何从列表中构建这一点。

最新更新