我需要一個接收包含八進制數的字串并將其轉換為十進制的程式。如果 String 包含任何不是 0 到 8 的數字,則該函式應回傳 0。
這是我得到的:
octoDec :: [Char] -> Int
octoDec [] = 0
octoDec (x:xs) = ((digitToInt(x)) * 8 ^(length xs)) octoDec xs
如果我輸入octoDec ['1','2','3'] 我得到83,這是預期的。但是,如何在不需要其他功能的情況下驗證用戶的?
編輯:我設法構建了一個函式來檢查一個數字是否只包含 0 到 7 之間的數字:
isOcto :: [Char] -> Bool
isOcto [] = True
isOcto (x:xs) | (digitToInt(x) > 0) && digitToInt(x) < 7 = isOcto (xs)
|otherwise = False
我想要的是將這兩個函式合并為一個并將零回傳到無效。
uj5u.com熱心網友回復:
如果您octoDec不僅要回傳結果,還要確定結果是否可能,請回傳 aMaybe Int而不是Int:
octoDec :: [Char] -> Maybe Int
octoDec [] = Just 0
octoDec (x:xs) = do
rest <- octoDec xs
let d = digitToInt x
guard $ d >= 0 && d <= 7
pure $ rest d * 8^length xs
如果條件不成立,guard函式 fromControl.Monad將使整個do塊回傳Nothing。
uj5u.com熱心網友回復:
首先,您需要使用Horner 方法將數字序列有效地轉換為單個值。
> foldl (\acc n -> 8*acc n) 0 (map digitToInt "123")
83
map digitToInt決議字串,
foldl (\acc n -> 8*acc n) 0是一個評估決議結果的函式。
horner :: [Int] -> Int
horner = foldl (\acc n -> 8*acc n) 0
parseString :: [Char] -> [Int]
parseString = fmap digitToInt
octoDec :: [Char] -> Int
octoDec = horner . parseString
但是,digitToInt不太正確:它可以接受大于 7 的數字,
> parseString "193"
[1,9,3]
并為根本不是數字的值引發例外。
> parseString "foo"
[15,*** Exception: Char.digitToInt: not a digit 'o'
我們可以寫一個更好的函式:
octalDigitToInt :: Char -> Maybe Int
octalDigitToInt c | c `elem` "01234567" = Just (digitToInt c)
| otherwise = Nothing
我們可以使用它來將八進制數轉換為數字序列,使用traverse代替fmap:
parseString' :: [Char] -> Maybe [Int]
parseString' = traverse octalDigitToInt
有效的八進制字串產生一個Just值:
> parseString' "123"
Just [1,2,3]
而無效的字串產生一個Nothing值:
> parseString' "193"
Nothing
> parseString' "foo"
Nothing
(可以將其traverse視為一個函式,它不僅將函式應用于值串列,而且僅在每個應用程式成功時才生成結果串列。更準確地說,它是sequence和的組合fmap:
traverse f = sequence . fmap f
sequence將 type[Maybe Int]的值“反轉”為 type的值的函式在哪里Maybe [Int]。)
With a more robust version of parseString, we need to adapt octoDec to handle the possibility that parsing will fail. We do that by using fmap to "lift" horner into the Maybe functor.
octoDec' :: [Char] -> Maybe Int
octoDec' s = fmap horner (parseString' s) -- or octoDec = fmap horner . parseString'
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/359170.html
