我正在讀取一個檔案,該檔案包含十六進制位元組。我將其讀入字串,將它們映射為單個單詞,然后將它們轉換為十進制值。
main = do
args <- getArgs
contents <- readFile (head args)
let singlewords = words contents
let intContents = map readHex singlewords
當我列印 intContents 的輸出時,我得到:
[[(5,"")],[(0,"")],[(0,"")],[(0,"")],[(5,"")],[(0,"")],[(0,"")],[(0,"")],[(48,"")],[(28,"")],[(75,"")],[(201,"")],[(134,"")],[(0,"")],[(0,"")]]
這些是正確的十進制值,但為什么它們與空字串配對?并作為單獨的嵌套串列?我只想要以下值:
[5,0,0,0,5,...]
我試著做:
intContents <- readHex contents
但我仍然只得到:
[(5," 00 00 00 05 00 00 00\n30 1C 4B C9 86 00 00")]
這只是第一個術語。任何幫助,將不勝感激。
編輯
現在了解 readHex 回傳的型別,我如何使用與我的代碼匹配的模式來獲取十進制數。
像這樣的某種定義?
intContents :: [(a, b)] -> a
intContents [(a, b)] = a
還是我只是將模式放在這樣的映射中?
let intContents = map ([(a, b)] (readHex singleWords)
注意:我嘗試了這兩種方法,只是出現了我不一定理解的錯誤
再次感謝任何幫助!
uj5u.com熱心網友回復:
如何使用與我的代碼匹配的模式來獲取十進制數。
一般是做不到的,因為有時候不會有十進制數!例如:
> readHex "lol"
[]
所以要做好這個任務,你必須決定在意外情況下你想發生什么。在我看來,這是幫助你思考需要撰寫什么代碼的型別系統。
您可以做出的一種選擇是這樣的:如果檔案的任何內容不是十六進制數字,則列印一條訊息并退出而不做任何其他事情。這是您可能擁有的最粗粒度的回應;為了完成這個任務,我們只需要記住到目前為止是否有錯誤。我們可以使用Maybe; 與串列一樣,我們需要匹配的模式是[]和_:_。所以:
readHexMaybe :: String -> Maybe Int
readHexMaybe s = case readHex s of
[] -> Nothing
(n, s') : otherResults -> Just n
如果您撰寫此代碼并打開警告,您會被告知s'并且otherResults不會被使用。這似乎是值得思考的事情!在s'位置上,一個成功的決議會給我們一個空字串;在這個otherResults位置上,一個成功的決議會給我們一個空串列。我們應該考慮在其他情況下該怎么做——型別系統再次幫助我們!
繼續我們要求一切順利的計劃,我們可以擴展它:
readHexMaybe :: String -> Maybe Int
readHexMaybe s = case readHex s of
[] -> Nothing
(n, "") : [] -> Just n
現在我們收到一個警告,說并非所有情況都包括在內。好的,如果s'倉位或otherResults倉位不為空怎么辦?估計Nothing又來了。所以:
readHexMaybe :: String -> Maybe Int
readHexMaybe s = case readHex s of
[] -> Nothing
(n, "") : [] -> Just n
(n, _) : _ -> Nothing
事實上,將成功的案例放在首位,Nothing其他情況全部回傳更簡單。我們還可以收縮[x]for的語法糖x:[]。
readHexMaybe :: String -> Maybe Int
readHexMaybe s = case readHex s of
[(n, "")] -> Just n
_ -> Nothing
好的,我們現在有一個更簡單的型別供閱讀。如果我們想從此類決議的整個集合中收集所有失敗,我們可以使用mapM. 所以:
readAllHexMaybe :: [String] -> Maybe [Int]
readAllHexMaybe = mapM readHexMaybe
最后,在 中main,我們可以將Nothings 變成給用戶的訊息,并將Justs 變成對 s 串列做一些有趣事情的延續[Int]。
main = do
args <- getArgs
fileName <- case args of
[fileName] -> return fileName
_ -> die "USAGE: ./whatever FILE"
contents <- readFile fileName
case readAllHexMaybe (words contents) of
Nothing -> die "File contained things that didn't look like hex numbers"
Just ns -> {- ... -}
uj5u.com熱心網友回復:
readHex有型別
readHex :: (Eq a, Num a) => ReadS a
這反過來是(見這里)
type ReadS a = String -> [(a, String)]
所以readHex在你的例子中似乎完全按照它的承諾去做并解釋了這些對。但是輸出到底是什么意思?上面鏈接的頁面告訴我們
型別 a 的決議器,表示為一個函式,該函式接受一個字串并將可能的決議串列作為 (a,String) 對回傳。
因此,在您的情況下,這些決議都會產生一個唯一值,這就是為什么您將這些對作為串列的單個專案。您可以使用以下模式匹配輕松提取這些值:
map (\[(a,_)] -> a)
但是你可能會在這個提取中付出更多的努力,因為如果你不完全匹配它會出錯[(a, _)]。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/462872.html
上一篇:在Haskell中撰寫函式
下一篇:創建一個IO字串
