Haskell:如何简洁地将多个String->IO ()函数依次作用于单个值
当然有更简洁的写法啦!你完全不用反复敲"test"这个参数——Haskell的函数式特性正好能帮你解决这个重复代码的问题。下面给你几种实用的方案:
方法1:用
mapM_一行搞定 这是最紧凑的写法,利用mapM_遍历函数列表,同时把每个函数绑定到"test"上并执行对应的IO动作:
main = mapM_ ($ "test") [op1, op2, op3]
这里的($ "test")是一个部分应用的函数,它接受任意一个String -> IO ()类型的函数(比如op1),返回f "test"。mapM_会严格按照列表顺序依次执行每个IO动作(先op1,再op2,最后op3)。
方法2:用
forM_(更贴近自然语言逻辑) 如果你觉得mapM_的参数顺序有点反直觉,可以用Control.Monad模块里的forM_,它把列表放在前面,操作函数放在后面,读起来更像“对列表里的每个元素执行操作”:
import Control.Monad (forM_) main = forM_ [op1, op2, op3] ($ "test")
效果和mapM_完全一致,只是写法更符合日常思考逻辑。
方法3:定义辅助函数(适合复杂do块场景)
如果你的main本身是一个do块,还可以先封装一个辅助函数,让代码可读性更强:
main = do let runOnTest = ($ "test") runOnTest op1 runOnTest op2 runOnTest op3
这种方式在需要插入其他IO操作时,不会让代码显得拥挤,逻辑也更清晰。
原理小补充
这里的核心是部分应用:($)是Haskell的右结合操作符,($ x)等价于\f -> f x——也就是把任意函数f绑定到参数x上。通过把这个部分应用的函数传给mapM_/forM_,我们就一次性给所有op函数绑定了"test",彻底避免重复书写。
内容的提问来源于stack exchange,提问作者matt
相关产品推荐
相关产品推荐

