Haskell中如何在do块内无中间变量链式调用Monad函数?
Monad场景下的无中间变量链式调用方案
当然有对应的实现方式,你可以使用Kleisli组合子来实现类似纯函数组合(.)的Monad链式调用,无需手动命名中间结果。
核心工具:Kleisli组合子
普通的函数组合符.用于组合纯函数(类型为(b -> c) -> (a -> b) -> a -> c),而Monad场景下的Kleisli组合子<=<(或其翻转版本>=>)专门用于组合Kleisli箭头——也就是类型为a -> m b的函数(这里m是任意Monad,比如你的例子里的Maybe)。
它们的类型签名:
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
改写你的代码
用<=<组合,顺序和纯函数组合.一致(从右到左):
r :: Int -> Maybe Int r = f4 <=< f3 <=< f2 <=< f1
如果你习惯从左到右的调用顺序(和do表达式的执行顺序一致),可以用>=>:
r :: Int -> Maybe Int r = f1 >=> f2 >=> f3 >=> f4
这两种写法完全等价于你原来的do表达式,自动处理了Monad值的绑定,不需要r1-r4这类中间变量。
另一种简洁写法:直接链式调用>>=
如果你不想用组合子,也可以直接用>>=链式调用,避免中间变量:
r :: Int -> Maybe Int r n = f1 n >>= f2 >>= f3 >>= f4
这种方式虽然需要显式传入参数n,但同样省去了中间变量的命名。
内容的提问来源于stack exchange,提问作者Jeff Huang
相关产品推荐
相关产品推荐

