Haskell中如何地道实现两个Maybe Int加1后相乘?能否用do块?
关于Maybe与Monad的问题解答
一、Maybe类型的优雅用法
Haskell里的Maybe本身已经是现成的Monad/Applicative实例,标准库已经帮你实现了所有必要的类型类实例,不需要额外编写代码来让它更易用——直接用就行。所谓“优雅”的写法,取决于场景和你习惯的风格,Monad(比如do块)、Applicative(你当前用的<*>风格)都是合理的选择。
二、用do块实现你的需求
当然可以用do块实现!针对你遇到的Advent of Code问题,do块的写法会更贴近“顺序式逻辑”,可读性很强:
test :: Maybe Int test = do x <- marker1Pos y <- marker2Pos return $ (x + 1) * (y + 1)
这段代码的逻辑非常直观:
- 从
marker1Pos中取出值x(如果是Nothing,整个do块直接返回Nothing,自动短路) - 再从
marker2Pos中取出值y(同样,遇到Nothing直接终止) - 最后计算
(x+1)*(y+1)并包装成Maybe返回
对比你之前的写法:
let test = Just (*) <*> ((+1) <$> marker1Pos) <*> ((+1) <$> marker2Pos)
两种写法都是正确的。do块更偏向“类命令式的可读性”,适合处理有依赖关系的操作;而Applicative风格更紧凑,适合组合独立的操作。你可以根据自己的习惯选择。
补充:Applicative写法的优化
其实你当前的Applicative写法也可以优化得更简洁,比如使用liftA2:
import Control.Applicative (liftA2) test = liftA2 (*) ((+1) <$> marker1Pos) ((+1) <$> marker2Pos)
或者进一步把(+1)的映射和乘法逻辑合并:
test = liftA2 (\x y -> (x+1)*(y+1)) marker1Pos marker2Pos
这些都是标准库原生支持的写法,不需要自己额外实现功能。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

