首页 > 解决方案 > 分解类型作为折叠中的种子

问题描述

我有以下问题:

我想计算第一个n数字的总和,并在每次迭代中保留每个添加数字的计数。因此我定义了一个类型:

data Avg = Avg { sum :: Int, count :: Int }

我需要在 a 中使用类型的种子,Avgfoldl'我需要在聚合器函数中分解它:

bang :: [Int] -> IO ()
bang ls@(x:xs) = printAvg $ foldl ' (\x y -> (x sum+y count+1) ) (Avg 0 0) ls

printAvg :: Avg -> IO ()
printAvg av = putStrLn . show (fromIntegral $ sum av / fromIntegral $ count av)

所以我的问题是:

给定一个类型data T = T { a :: Int, b :: Int }并给定一个 type 变量myvarT我如何将它放置为模式匹配而不是它的数据构造函数?

在我的示例中,它foldl'采用列表Avg中的seed和一个元素。

我需要(\x y-> (x sum+y count+1)) 而不是 (\x y-> (Avg sum+y count+1)).

标签: haskell

解决方案


一些可能的解决方案:

(\ (Avg s c) y -> Avg (s + y) (c + 1))
-- equivalent to the longer
(\ x y -> case x of Avg s c -> Avg (s + y) (c + 1))

-- mentioning the fields name explicitly
(\ Avg{sum=s, count=c} y -> Avg (s + y) (c + 1))

-- using the RecordWildCards extension
(\ Avg{..} y -> Avg (sum + y) (count + 1))

-- using the two projections
(\ x y -> Avg (sum x + y) (count x + 1))

甚至,调整你的代码

bang::[Int]->IO()
bang ls@(x:xs) = printAvg $ foldl' foo (Avg 0 0) ls
   where
   foo (Avg s c) y = Avg (s + y) (c+ 1)

let foo .. in ..也可以使用)


推荐阅读