我怎样才能优雅地处理 maybe monad 的 Nothing 分支?
How can I handle Nothing branch of maybe monad gracefully?
data Union = F Float | I Int | S String
getUnionFromString :: String -> Union
getUnionFromString str =
case (readMaybe str :: Maybe Int) of
Just i -> I i
Nothing ->
case (readMaybe str :: Maybe Float) of
Just f -> F f
Nothing -> S str
getStr (F f) = "Float " ++ show f
getStr (I i) = "Int " ++ show i
getStr (S s) = "String " ++ s
main = do
str <- getLine
putStrLn $ getStr (getUnionFromString str)
我想制作一个将字符串转换为联合类型(Float | Int | String) 的函数。所以我用 readMaybe
来找出字符串的类型。然后,使用 case-of 来处理 Just
和 Nothing
分支。我认为它不能用 Maybe
的 Monad
行为来应对这种情况,因为我不想在 Nothing
出来时停止计算,我想处理 Nothing
案件。 getUnionFromString
函数有没有更好的写法?
我们可以使用 Control.Applicative.<|>
来简化尝试不同表达式的逻辑,如果计算结果为 Nothing
:
Prelude> import Control.Applicative
Prelude Control.Applicative> Just 1 <|> Nothing
Just 1
Prelude Control.Applicative> Just 1 <|> Just 2
Just 1
Prelude Control.Applicative> Nothing <|> Just 1
Just 1
Prelude Control.Applicative> Nothing <|> Nothing
Nothing
将它与 Data.Maybe.fromMaybe
一起使用,我们可以将代码简化为:
getUnionFromString :: String -> Union
getUnionFromString str = fromMaybe (S str) $ (I <$> readMaybe str) <|> (F <$> readMaybe str)
Haskell 的类型推断能够找出第一个 readMaybe
想要一个 Maybe Int
而第二个想要 Maybe Float
,而无需我们明确要求它。
完整代码:
import Control.Applicative
import Data.Maybe (fromMaybe)
import Text.Read
data Union = F Float | I Int | S String
getUnionFromString :: String -> Union
getUnionFromString str = fromMaybe (S str) $ (I <$> readMaybe str) <|> (F <$> readMaybe str)
getStr (F f) = "Float " ++ show f
getStr (I i) = "Int " ++ show i
getStr (S s) = "String " ++ s
main = do
str <- getLine
putStrLn $ getStr (getUnionFromString str)
data Union = F Float | I Int | S String
getUnionFromString :: String -> Union
getUnionFromString str =
case (readMaybe str :: Maybe Int) of
Just i -> I i
Nothing ->
case (readMaybe str :: Maybe Float) of
Just f -> F f
Nothing -> S str
getStr (F f) = "Float " ++ show f
getStr (I i) = "Int " ++ show i
getStr (S s) = "String " ++ s
main = do
str <- getLine
putStrLn $ getStr (getUnionFromString str)
我想制作一个将字符串转换为联合类型(Float | Int | String) 的函数。所以我用 readMaybe
来找出字符串的类型。然后,使用 case-of 来处理 Just
和 Nothing
分支。我认为它不能用 Maybe
的 Monad
行为来应对这种情况,因为我不想在 Nothing
出来时停止计算,我想处理 Nothing
案件。 getUnionFromString
函数有没有更好的写法?
我们可以使用 Control.Applicative.<|>
来简化尝试不同表达式的逻辑,如果计算结果为 Nothing
:
Prelude> import Control.Applicative
Prelude Control.Applicative> Just 1 <|> Nothing
Just 1
Prelude Control.Applicative> Just 1 <|> Just 2
Just 1
Prelude Control.Applicative> Nothing <|> Just 1
Just 1
Prelude Control.Applicative> Nothing <|> Nothing
Nothing
将它与 Data.Maybe.fromMaybe
一起使用,我们可以将代码简化为:
getUnionFromString :: String -> Union
getUnionFromString str = fromMaybe (S str) $ (I <$> readMaybe str) <|> (F <$> readMaybe str)
Haskell 的类型推断能够找出第一个 readMaybe
想要一个 Maybe Int
而第二个想要 Maybe Float
,而无需我们明确要求它。
完整代码:
import Control.Applicative
import Data.Maybe (fromMaybe)
import Text.Read
data Union = F Float | I Int | S String
getUnionFromString :: String -> Union
getUnionFromString str = fromMaybe (S str) $ (I <$> readMaybe str) <|> (F <$> readMaybe str)
getStr (F f) = "Float " ++ show f
getStr (I i) = "Int " ++ show i
getStr (S s) = "String " ++ s
main = do
str <- getLine
putStrLn $ getStr (getUnionFromString str)