[英]calling function after input in haskell
這是家庭作業的一部分。 我需要編寫一個從輸入讀取信息直到空行的函數。 在該函數之后,將第一,第三,第五...行符號作為一個字符串,將第二,第四...作為另一字符串。 簽名combine :: IO (String , String)
我編寫了一個函數,該函數將列表作為參數,並將1,3,5 ..放在一個String
將2,4,6個符號放在另一個String
。 功能在這里:
intotwo (x : xs)
= let
(us , vs)
= intotwo xs
in
(x : vs , us)
intotwo _
= ([] , [])
我還編寫了一個讀取輸入的代碼:在這里:
combine
= do
lines <- getLine
if null lines
then return ([], [])
else do
linesagain <- combine
return --what should I return?
有人可以幫我完成作業嗎(可選:提供一些技巧)?
我會給您一些提示,以幫助您解決問題。
首先,為您定義的所有函數提供類型是一個巨大的幫助。 這使編譯器可以立即告訴您函數是否沒有按照您認為的那樣做。 當您需要將程序的不同部分連接在一起時,它也可以為您提供幫助。
其次,每個功能僅解決一個問題是一個很好的主意。 您的intotwo函數很好地遵循了這一點,它很好地完成了拆分列表的工作。 但是,您的Combine函數似乎正在嘗試做太多事情,這將使編寫變得更加困難。 我會將那個功能分成兩個較小的功能。
最后,有一個非常有用的特殊函數,稱為undefined
。 這可以匹配任何類型,並有助於您編寫函數。 訣竅是從整個函數等於未定義開始(並且編譯但在運行時崩潰),並逐步改進該函數,直到它完成您想要的操作並且其中沒有更多未定義為止。
因此,首先,我將一個類型簽名添加到intwo函數中。 類型是[a] -> ([a], [a])
。
接下來,我將編寫一個函數,該函數從輸入中讀取行,直到遇到空行,然后返回讀取的行的列表。 該函數的類型為:
readLinesUntilEmpty :: IO [String]
readLinesUntilEmpty = undefined
一個幾乎可以做到這一點的實現是這樣的:
readLinesUntilEmpty = do
nextLine <- getLine
rest <- readLinesUntilEmpty
return (nextLine : rest)
但是,這永遠不會停止讀取(請注意如何不檢查nextLine是否為空)。
以下函數顯示了如何執行此操作(但我省略了一些實現):
readLinesUntilEmpty = do
nextLine <- getLine
case nextLine of
"" -> do
undefined -- TODO fix me
_ -> do
undefined -- TODO fix me
您應該能夠從那里找出其余的內容。
接下來,您的intotwo函數將返回兩個字符串列表,但是希望您將它們再次結合在一起。 例如["this", "that"]
應該變成"this\\nthat"
。 此類函數的類型為[String] -> String
:
joinLines :: [String] -> String
joinLines = undefined -- TODO
這個函數比inttotwo函數更容易編寫,因此應該沒問題。
最后,您可以將這三個功能鏈接在一起以獲得結果:
combine :: IO (String, String)
combine = do
lines <- readLinesUntilEmpty
let (oddLines, evenLines) = intotwo lines
return $ (joinLines oddLines, joinLines evenLines)
由於需要讀取多個字符串,因此需要遞歸輸入。 或者,您可以只使用getContents,但是我不確定它是否適合交互式I / O。 像這樣:
combine = getContents
>>= return . intotwo
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.