You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何替代case of精简代码?求优化嵌套case匹配的fmap代码方案

Alternatives to case of for Cleaner Haskell Code

Great question! Nested case expressions can quickly make code feel clunky and hard to follow—especially when dealing with nested Maybe values like in your example. Let's break down both general alternatives to case of and a cleaner way to rewrite your specific code.

General Alternatives to case of for Maybe Values

When working with Maybe, you have several idiomatic alternatives to nested case statements:

  • Monadic Do Notation: Since Maybe is a monad, you can use do-notation to flatten nested checks into linear, readable code. Any step that returns Nothing will short-circuit the entire block, just like your nested case statements.
  • Maybe Combinators: Use functions like >>= (bind), >> (sequence without using the result), and <$> (fmap) to chain operations on Maybe values. This avoids explicit case matching entirely.
  • The maybe Helper Function: This is a built-in function that replaces basic case checks for Maybe. It takes a default value, a function to run on the Just value, and the Maybe itself: maybe defaultValue f maybeValue.
  • Lens Operations: If you're already using lens (like your ^. operator), tools like ^? (safe lens access, returns Maybe), preview, and filtered let you concisely traverse nested optional values without case statements.

Cleaning Up Your Specific Code

Your original code is trying to extract the sSheetId only if both sProperties and sTitle exist (i.e., are Just values). Here are several cleaner implementations:

Version 1: Do Notation (Most Readable)

This flattens the nested cases into a linear flow that's easy to follow:

fmap (\eachSheet -> do
    sheetProperties <- eachSheet ^. sProperties
    _ <- sheetProperties ^. sTitle  -- We don't need the title value, just its existence
    pure (sheetProperties ^. sSheetId)) listOfSheets

Version 2: Monadic Combinators (Concise)

Using >>= and >> to chain the checks without do-notation:

fmap ( (>>= \sp -> sp ^. sTitle >> pure (sp ^. sSheetId)) . (^. sProperties) ) listOfSheets

Version 3: maybe Function (Functional Style)

Replace each nested case with a maybe call for a more point-free feel:

fmap (maybe Nothing (\sp -> maybe Nothing (\_ -> sp ^. sSheetId) (sp ^. sTitle)) . (^. sProperties)) listOfSheets

Version 4: Lens-Specific Approach

Leverage lens's safe access (^?) and traversal tools to make it even more idiomatic:

fmap (\eachSheet -> do
    sp <- eachSheet ^? sProperties . _Just
    _ <- sp ^? sTitle . _Just
    pure (sp ^. sSheetId)) listOfSheets

Or an even more compact lens version using preview and filtered:

import Control.Lens (filtered, preview)

fmap (preview (sProperties . _Just . filtered (\sp -> isJust (sp ^. sTitle)) . sSheetId)) listOfSheets

All these versions behave exactly like your original code but are much easier to read and maintain. Which one you choose depends on your preference for readability vs. conciseness, and how deeply you're already using lens in your codebase.

内容的提问来源于stack exchange,提问作者Samuel D'costa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:13:35