Is it possible to nest guards in Haskell?

前端 未结 8 925
野的像风
野的像风 2020-12-10 16:52

Haskell newbie here, trying to write code to parse math expressions. Code:

isDigit :: Char -> Bool
isDigit c = c >= \'0\' && c <= \'9\'

pars         


        
8条回答
  •  情深已故
    2020-12-10 17:03

    Recent GHC now has MultiWayIf:

    {-# LANGUAGE MultiWayIf #-}
    
    parseNumber :: String -> Maybe (String, String)
    parseNumber [] = Just ("", "")
    parseNumber (h:ls)
      | isDigit h = if
        | p == Nothing -> Just ([h], ls)
        | otherwise    -> Just (h:fst d, snd d)
      | h == '.'  = if
        | p == Nothing             -> Nothing
        | not ('.' `elem` (snd d)) -> Just (h:(fst d), snd d)
      | otherwise = Nothing
      where p@(~(Just d)) = parseNumber ls
    

    But this is better written slightly differently anyhow, without the partiality.

    {-# LANGUAGE MultiWayIf #-}
    
    parseNumber :: String -> Maybe (String, String)
    parseNumber [] = Just ("", "")
    parseNumber (h:ls)
      | isDigit h = if
        | Nothing <- p -> Just ([h], ls) -- PatternGuards, on by default
        | Just d  <- p -> Just (h:fst d, snd d)
      | h == '.'  = if
        | Nothing <- p                         -> Nothing
        | Just d  <- p, not ('.' `elem` snd d) -> Just (h:(fst d), snd d)
      | otherwise = Nothing
      where p = parseNumber ls
    

    and you may as well use maybe.

    parseNumber :: String -> Maybe (String, String)
    parseNumber "" = Just ("", "")
    parseNumber (h:hs)
      | isDigit h = maybe (Just ([h], hs)) (\(num, rest') -> Just (h:num, rest')) rest
      | h == '.'  = maybe Nothing (\(num, rest') -> if '.' `elem` num then Nothing
                                                    else Just (h:num, rest')
                                  ) rest -- This logic is a bit wonky; it doesn't really work
      | otherwise = Nothing
      where rest = parseNumber hs
    

提交回复
热议问题