[英]How to return user input as a string instead of printing it out or getting an IO String in Haskell?
下面是我到目前为止的代码:
type Deck = [Card]
data Card = Card {question :: String, answer :: String} deriving (Show)
askForNextCommand deck = do
putStrLn "What would you like to do?"
userInput <- getLine
return userInput
loop :: Deck -> IO ()
loop deck = print $ askForNextCommand deck
main :: IO ()
main = loop []
我遇到的问题是askForNextCommand
函数。 我希望能够在这样的另一个函数中使用用户输入:
有一副纸牌,每张纸牌都包含一个问题和答案,可以向用户提问,将更多卡添加到列表中,删除卡等。
当我学习Python时,我做了一个类似的程序,所以我现在尝试在Haskell中制作它。
我还有另一个函数接受输入,并根据输入的内容对其进行处理:
doCommand command deck
| command == "add" = addFunc deck
| command == "remove" = removeFunc deck
| otherwise = doCommand (askForNextCommand deck) deck
问题是我不知道如何获取命令参数作为用户输入。 我希望askForNextCommand
提示用户,然后以字符串形式返回他们的输入,但是现在我已经搜索了大约半小时,无法找到任何内容。 我敢肯定这是一个简单的解决方法,但是我不确定要看哪里。 任何帮助将不胜感激。
首先,始终为您的顶级绑定提供类型签名。 这将极大地帮助您找出类型错误。
askForNextCommand :: Deck -> IO String
askForNextCommand deck = do
putStrLn "What would you like to do?"
userInput <- getLine
return userInput
顺便说一下,最后两行是反模式。 编写上述函数的标准方法是:
askForNextCommand :: Deck -> IO String
askForNextCommand deck = do
putStrLn "What would you like to do?"
getLine
到现在为止还挺好。 现在到罪魁祸首:
loop :: Deck -> IO ()
loop deck = print $ askForNextCommand deck
这里askForNextCommand deck
的类型为IO String
(请参阅上一个签名)。 函数print
尝试将其转换为字符串(从技术上来说,转换为类型类Show
),但是为此,它将需要一个函数show :: IO String -> String
,这是无法构造的。
实际上, IO String -> String
会神奇地将与用户交互并产生字符串(例如getLine
)的一段代码转换为一段无需用户交互就产生该字符串的代码。 我们不能在没有实际执行IO的情况下从getLine
提取字符串,所以这是不可能的。
这是更正的版本:
loop :: Deck -> IO ()
loop deck = do
cmd <- askForNextCommand deck
print cmd
或者,等效地,
loop :: Deck -> IO ()
loop deck = askForNextCommand deck >>= print
上面的代码运行IO,获取字符串,然后打印出来。 print
现在收到一个String
,所以一切都很好。
拇指规则是:你可以提取使用从IO单子的事情x <- someIOValue
一个里面do
。 要注意的是,您只能在再次返回IO类型的函数中执行此操作。
如果您想了解更多有关Haskell中的单子和朋友的信息,那么有很棒的博客文章Functors,Applicatives和Picture中的Monads ,它以实用且轻巧的方式对其进行了解释。
最后,上面的代码将添加一些额外的引号。 如果要避免使用引号,请使用putStrLn
而不是print
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.