我可以用什么代替 `case of` 来减少代码?

what can i use instead of `case of` to reduce the code?

fmap ( \eachSheet -> case (eachSheet ^. sProperties) of
  Just sheetProperties -> case (sheetProperties ^. sTitle) of
    Just sheets -> (sheetProperties ^. sSheetId)    
    Nothing -> Nothing
  Nothing -> Nothing ) listOfSheets

比大小写匹配更好的方法

特定模式

     case f foo of
       Just bla -> case g bla of
          Just muh -> h muh
       Nothing -> Nothing

Maybe monad 的特征。该实例定义为

instance Monad Maybe where
  return = Just
  Nothing >>= _ = Nothing
  Just x >>= f = f x

所以你可以将上面的case构造重写为

    f foo >>= \bla -> g bla >>= \muh -> h muh

可以通过使用 do 语法

来提高可读性
    do
      bla <- f foo
      muh <- g bla
      h muh

或 eta 减少和 Kleisli-composition operator

     (f >=> g >=> h) foo

在你的例子中,后者实际上是不可能的,因为最里面的函数不使用 sheets 而是再次使用 sheetProperties,但仍然可以使用 do 符号。

你在这里基本上展示的是 Maybe monad 的使用,所以我们可以这样写:

fmap (\s -> (s ^. sProperties) >>= \sheetProperties -> (sheetProperties ^. sTitle) >> (sheetProperties ^. sSheetId)) listOfSheets

因为 Maybe monad 定义为:

instance Monad Maybe where
    return = Just
    (>>=) Nothing _ = Nothing
    (>>=) (Just x) f = f x

或者我们也可以写成do符号,虽然基本上是一样的:

fmap f listOfSheets
    where f eachSheet = do
        sheetProperties <- eachSheet ^. sProperties
        sheets <- sheetProperties ^. sTitle
        sheetProperties ^. sSheetId