簡體   English   中英

我怎樣才能優雅地處理也許 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 and Nothing分支。 我認為它無法用MaybeMonad行為來應對這種情況,因為我不想在Nothing出來時停止計算,我想處理Nothing情況。 有沒有更好的方法來編寫getUnionFromString函數?

如果計算結果為Nothing ,我們可以使用Control.Applicative.<|>來簡化嘗試不同表達式的邏輯:

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM