这是家庭作业的一部分.我需要编写一个函数,从输入读取信息直到空行.之后,该函数将第一个,第三个,第五个...行符号作为一个字符串,第二个,第四个...作为另一个字符串.签名是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 _
= ([] , [])
Run Code Online (Sandbox Code Playgroud)
我也写了一个读取输入的代码:它在这里:
combine
= do
lines <- getLine
if null lines
then return ([], [])
else do
linesagain <- combine
return --what should I return?
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮我完成我的作业(可选:提供一些提示)?
我会给出一些提示来帮助您解决问题.
首先,为您定义的所有函数提供类型是一个巨大的帮助.这样,编译器可以立即告诉您函数是否正在执行您认为正在执行的操作.当您需要将程序的不同部分连接在一起时,它还可以帮助您.
其次,每个功能只解决一个问题是一个非常好的主意.你的intotwo函数很好地遵循这个功能,它可以很好地分割列表.然而,你的组合功能似乎试图做太多,这将使它更难写.我会将该功能分成两个较小的功能.
最后,有一个非常有用的特殊功能叫做undefined.这匹配任何类型,并帮助您编写函数.诀窍是从整个函数开始等于未定义(并编译但在运行时崩溃),并逐步改进函数,直到它完成你想要的并且没有更多的undefines.
首先,我会在intotwo函数中添加一个类型签名.类型是[a] -> ([a], [a]).
接下来,我将编写一个函数,从输入读取行直到它到达空行,然后返回读取的行列表.这个函数有类型:
readLinesUntilEmpty :: IO [String]
readLinesUntilEmpty = undefined
Run Code Online (Sandbox Code Playgroud)
几乎这样做的实现是这样的:
readLinesUntilEmpty = do
nextLine <- getLine
rest <- readLinesUntilEmpty
return (nextLine : rest)
Run Code Online (Sandbox Code Playgroud)
但是这永远不会停止读取(注意未检查nextLine是否为空).
以下函数显示了如何执行此操作(但我将部分实现保留):
readLinesUntilEmpty = do
nextLine <- getLine
case nextLine of
"" -> do
undefined -- TODO fix me
_ -> do
undefined -- TODO fix me
Run Code Online (Sandbox Code Playgroud)
你应该能够从那里弄清楚剩下的.
接下来,你的intotwo函数返回两个字符串列表,但是你应该再次将它们连接在一起.例如["this", "that"]应该变成"this\nthat".这种功能的类型是[String] -> String:
joinLines :: [String] -> String
joinLines = undefined -- TODO
Run Code Online (Sandbox Code Playgroud)
这是一个比inttotwo func更容易编写的函数,所以你应该没问题.
最后,您可以将这三个函数链接在一起以获得结果:
combine :: IO (String, String)
combine = do
lines <- readLinesUntilEmpty
let (oddLines, evenLines) = intotwo lines
return $ (joinLines oddLines, joinLines evenLines)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
539 次 |
| 最近记录: |