haskell - 分解类型作为折叠中的种子
问题描述
我有以下问题:
我想计算第一个n
数字的总和,并在每次迭代中保留每个添加数字的计数。因此我定义了一个类型:
data Avg = Avg { sum :: Int, count :: Int }
我需要在 a 中使用类型的种子,Avg
但foldl'
我需要在聚合器函数中分解它:
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 变量myvar
,T
我如何将它放置为模式匹配而不是它的数据构造函数?
在我的示例中,它foldl'
采用列表Avg
中的seed
和一个元素。
我需要(\x y-> (x sum+y count+1))
而不是 (\x y-> (Avg sum+y count+1))
.
解决方案
一些可能的解决方案:
(\ (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 ..
也可以使用)
推荐阅读
- airflow - Airflow 使用 ExternalTaskSensor 手动运行 DAG
- c# - 从实体框架中提取列表列表
- python - 传递函数将忽略的参数
- javascript - 如何在 node.js 函数中应用 Promise
- postgresql - 错误:运算符不存在:数字 = 字符变化
- spring - MVC 中的 Spring Cache - 可以使用自动装配进行查找吗?
- .net - Docker 容器启动(“docker run”)但立即停止(ASP .NET MVC api-REST 解决方案)
- java - 使用 Java 在 XML 中设置嵌入字段的文本
- sql - 连接具有相同键的表,第二个表有多个键值,第二个表的行必须具有相同的列值
- jenkins - Docker 上的詹金斯。-- Hello World 示例构建失败