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分支。我認為它無法用 的Monad行為來應對這種情況Maybe,因為我不想在Nothing退出時停止計算,我想處理Nothing案例。有沒有更好的方法來撰寫getUnionFromString函式?
uj5u.com熱心網友回復:
如果計算結果為 ,我們可以使用它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想要 aMaybe 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)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/487874.html
