[英]haskell-problem: io string -> [int]
你好偉大的程序員在那里,
我正在使用haskell的第一步,並且有一個令我困惑的功能:
import Data.List.Split
getncheck_guesslist = do
line <- getLine
let tmp = splitOneOf ",;" line
map read tmp::[Int]
splitOneOf在Data.List.Split中(我用cabal安裝拆分安裝) splitOneOf :: (Eq a)=> [a]->[a]->[[a]]
從錯誤我得到它有一些類型不正確 - 但不知道如何解決這個沖突,因為IO對我來說仍然是一個謎
我想讀取用逗號或分號分隔的整數輸入,並得到一個整數列表,這樣:
提前感謝您的想法和提示 - 您的ε/ 2
當您編寫使用IO monad的函數時,要從函數返回的任何值也必須位於IO monad中。
這意味着,您不必返回類型為[Int]
的值,而是返回類型為IO [Int]
。 要做到這一點,你可以使用return
函數,它將值“包裝”到IO
(它實際上適用於任何 monad)。
只需更改最后一行以使用return
包裝您的值,如下所示:
getncheck_guesslist = do
line <- getLine
let tmp = splitOneOf ",;" line
return (map read tmp :: [Int])
在Haskell中執行此操作的“正確方法”是將IO與其他所有內容分開。 您的代碼的直接翻譯將是這樣的:
getncheck_guesslist :: IO [Int]
getncheck_guesslist = do line <- getLine -- get
return (check_guesslist line) -- check
check_guesslist :: String -> [Int]
check_guesslist line = let tmp = splitOneOf ",;" line
in map read tmp
請注意, getncheck_guesslist
只是一個IO操作。 該函數沒有輸入參數 ,即使它確實需要來自getLine
(IO)輸入 。
另請注意, getncheck_guesslist
是對getLine
IO操作的簡單修改。 是不是有一個組合器可以讓我推動一個函數來對monad中的值進行操作? 停止。 霍格時間!
我有一個功能(a -> b)
。 我有一個輸入類型的值,但它被卡在monad ma
。 我想執行的單子里面的功能,所以其結果將不可避免地被卡在單子太mb
。 把它們放在一起,我們hoogle (a -> b) -> ma -> mb
。 瞧, fmap
正是我們想要的。
get_guesslist = check_guesslist `fmap` getLine
-- or, taking it a step further
get_guesslist = (map read . splitOneOf ",;") `fmap` getLine :: IO [Int]
最后要注意的,只要你喜歡的名字代碼的方法somethingAndSomethingElse
,通常最好的編碼風格來寫和調用something
和somethingElse
作為兩個獨立的方法。 對於最終版本,我只是將其重命名為get_guesslist
,因為從概念上講它就是它的作用。 它得到了作為Ints列表的猜測。
作為最后的最后一點,我已經離開了baroap開始的地步。 ;) fmap
與<$>
相同。
如果IO
monad中存在某些內容,則無法將其帶到純外部世界進行進一步處理。 相反,您傳遞純函數以在IO
內的函數內部工作。
最后,您的程序讀取一些輸入並寫入一些輸出,因此您的主要功能將用於IO
,否則您將無法輸出任何內容。 而不是讀IO String
和創建[Int]
通過消耗該函數[Int]
到您的主要功能和使用它里面do
。
import Data.List.Split
import Control.Applicative
getncheck_guesslist :: IO [Int]
getncheck_guesslist = map read . splitOneOf ",;" <$> getLine
每次代碼陷入foo >>= return . bar
foo >>= return . bar
,該你做的,你不使用你的單子的單子功能脫糖的DO-塊(和糾正錯誤類型),但只有它的仿函數部分,即,不客氣的說,你是不是用搞亂IO
部分的類型,但與a
的IO a
:
(<$>) :: (Functor f) => (a -> b) -> f a -> f b
( fmap
將是<$>
的非中綴名稱。兩者都與map
密切相關。)
上面的代碼對於ad-hoc代碼來說非常慣用,但是干凈的代碼看起來就像
import Data.Maybe
maybeRead :: Read a => String -> Maybe a
maybeRead = fmap fst . listToMaybe . reads
-- That fmap is using "instance Functor Maybe"
parseGuessList :: String -> [Int]
parseGuessList = catMaybes . map maybeRead . splitOneOf ",;"
getncheck_guesslist = parseGuessList <$> getLine
,或者,如果您不想忽略非int輸入但是錯誤輸出,
parseGuessList xs = if success then Just . catMaybes $ ys else Nothing
where ys :: String -> [Mabye Int]
ys = map maybeRead . splitOneOf ",;" $ xs
success = all isJust ys
(請注意,我只證明代碼是正確的,但實際上沒有嘗試過。)
如果它比你想要使用正確的解析庫更復雜,我想。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.