Haskell技术问题:如何从元组调用函数并交替应用f1、f2到列表
解决交替应用函数到列表的问题
嘿,我来帮你拆解下这个问题:
首先,你的报错根源不在函数应用的写法上(你写的(snd p) (fst p)这种函数调用方式是没问题的),问题出在你用来生成交替函数的repeat [f1, f2]上。
为什么原代码会报错?
repeat [f1, f2]会生成一个无限重复整个列表的序列,也就是:[f1,f2], [f1,f2], [f1,f2], ...
所以当你和[1,2,3,4]zip之后,每个元组p的结构是(1, [f1,f2])、(2, [f1,f2])……这时候snd p拿到的是一个函数列表,而不是单个函数。Haskell自然会报错,因为它期望snd p是一个能接受Integer参数的函数,结果实际拿到的是[Integer -> Integer]类型的列表,类型完全不匹配。
正确的写法:用cycle替代repeat
如果你想交替获取f1和f2,应该用cycle [f1, f2]——它会把输入的列表循环展开成单个元素的无限序列:f1, f2, f1, f2, ...
修改后的代码如下(我给f1、f2加了具体实现方便你测试):
f1 :: Integer -> Integer f1 x = x * 2 -- 示例函数1:乘2 f2 :: Integer -> Integer f2 x = x + 1 -- 示例函数2:加1 -- 交替应用函数到列表元素 result = [ func num | (num, func) <- zip [1,2,3,4] (cycle [f1, f2]) ]
运行这段代码会得到[2, 3, 6, 5],正好对应f1(1)、f2(2)、f1(3)、f2(4)的结果,完全符合你交替应用函数的需求。
额外说明
如果你坚持想用repeat(虽然没必要),那你需要从每个列表里按索引取对应的函数,但这会多一步操作,而且达不到交替的效果,比如:
-- 这只是演示,不推荐这么写 bad_result = [ ((snd p) !! (num `mod` 2)) num | (num, p) <- zip [1,2,3,4] (repeat [f1, f2]) ]
显然这种写法既冗余又容易出错,远不如用cycle简洁直观。
内容的提问来源于stack exchange,提问作者coder_bro
相关产品推荐
相关产品推荐

