繁体   English   中英

如何在Haskell中将用户输入作为字符串返回而不是打印出来或获取IO字符串?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM