Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell-返回用户输入整数的循环_Haskell_Recursion_Io - Fatal编程技术网

Haskell-返回用户输入整数的循环

Haskell-返回用户输入整数的循环,haskell,recursion,io,Haskell,Recursion,Io,我想写一个函数,当被调用时,它会不断地请求用户输入,直到输入可以被读取为整数为止(此时整数返回到一个可能的do块,在该块中函数首先被调用) 我的代码在这里: lp_reqInt = do input1 <- getLine if ((readMaybe input1 :: Maybe Int) == Nothing) then do putStrLn "(integer input required, please try ag

我想写一个函数,当被调用时,它会不断地请求用户输入,直到输入可以被读取为整数为止(此时整数返回到一个可能的do块,在该块中函数首先被调用)

我的代码在这里:

lp_reqInt = 
  do
    input1 <- getLine
    if ((readMaybe input1 :: Maybe Int) == Nothing)
      then do 
             putStrLn "(integer input required, please try again)"
             lp_reqInt 
      else let output = fromMaybe (-666) (readMaybe input1 :: Maybe Int)
    return output
lp_需求=
做

input1您似乎有点误解了
do
-表示法的工作原理

我会给你一个“正确”的版本,我们可以解决这个问题:

lp_reqInt = do
    input1 <- getLine
    let maybeInput = readMaybe input1 :: Maybe Int
    if maybeInput == Nothing
      then do putStrLn "(integer input required, please try again)"
              lp_reqInt 
      else return $ (\(Just x) -> x) maybeInput
lp_requint=do
输入1 x)可输入
注意顶部的
let
-语句。我可以在这里执行
let
-语句,而不是在
-语句中执行
let
-
,因为它位于
do
-块的顶层。当您编写
let output=fromMaybe(…)
时,它不在
do
-块的顶层,而是在
if
-语句的第二部分,因此它将不起作用


正是因为这个原因,您得到了一个解析错误:GHC期望在
中出现一个附带的

您似乎有点误解了
符号是如何工作的

我会给你一个“正确”的版本,我们可以解决这个问题:

lp_reqInt = do
    input1 <- getLine
    let maybeInput = readMaybe input1 :: Maybe Int
    if maybeInput == Nothing
      then do putStrLn "(integer input required, please try again)"
              lp_reqInt 
      else return $ (\(Just x) -> x) maybeInput
lp_requint=do
输入1 x)可输入
注意顶部的
let
-语句。我可以在这里执行
let
-语句,而不是在
-语句中执行
let
-
,因为它位于
do
-块的顶层。当您编写
let output=fromMaybe(…)
时,它不在
do
-块的顶层,而是在
if
-语句的第二部分,因此它将不起作用


正是因为这个原因,您得到了一个解析错误:GHC期望在
中出现一个附带的

另一个答案讨论了问题所在以及最小修复。除了让您继续编写代码的最简单的事情之外,我认为展示惯用的修复方法可能也很有趣,即使用模式匹配而不是
if
。因此:

lp_reqInt :: IO Int
lp_reqInt = do
  input1 <- getLine
  case readMaybe input1 of
    Nothing -> do
      putStrLn "(integer input required, please try again)"
      lp_reqInt
    Just n -> return n
lp_需求::IO需求
lp_requint=do
输入1 do
putStrLn“(需要整数输入,请重试)”
lp_需求
只需n->返回n

这不需要在
fromaybe
中使用奇怪的回退
-666
,这很好。使用模式匹配而不是
(==)
还有一个更微妙的优势:它不需要底层类型具有
Eq
实例。对于
Int
有一个,因此此代码没有优势,但在其他情况下,它可能更重要。我还将字体签名提升到了顶层;关于这个习语的进一步讨论。

另一个答案讨论了哪里出了问题,以及最小的修复。除了让您继续编写代码的最简单的事情之外,我认为展示惯用的修复方法可能也很有趣,即使用模式匹配而不是
if
。因此:

lp_reqInt :: IO Int
lp_reqInt = do
  input1 <- getLine
  case readMaybe input1 of
    Nothing -> do
      putStrLn "(integer input required, please try again)"
      lp_reqInt
    Just n -> return n
lp_需求::IO需求
lp_requint=do
输入1 do
putStrLn“(需要整数输入,请重试)”
lp_需求
只需n->返回n

这不需要在
fromaybe
中使用奇怪的回退
-666
,这很好。使用模式匹配而不是
(==)
还有一个更微妙的优势:它不需要底层类型具有
Eq
实例。对于
Int
有一个,因此此代码没有优势,但在其他情况下,它可能更重要。我还将字体签名提升到了顶层;对于这个习语的进一步讨论。

前面的答案很好,但我只想用另一种合理的方法来扩展这个主题,让那些最终在这里搜索的不是OP想要的东西,而是相关的东西

由于主题提到了用户输入
IO
)和整数
Maybe Int
),我们最终得到了类似
IO(Maybe Int)
的类型。这些类型在Monad转换器下表达得最好,即
maybetio Int
,它们也可以很好地充当
Alternative
类成员

Haskell为这些情况提供了极好的解决方案,因此我们可以像这样处理相同的问题

import Control.Monad (msum)
import Control.Monad.Trans.Maybe
import Control.Monad.Trans (lift)
import Text.Read (readMaybe)

lp_reqInt :: MaybeT IO Int
lp_reqInt = msum . repeat $ (lift . putStrLn) "Enter an integer.." >>
                            (MaybeT $ readMaybe <$> getLine)

前面的答案很好,但我只是想用另一种合理的方法来扩展这个主题,让那些最终在这里搜索OP要求的内容,而不是相关的内容的人

由于主题提到了用户输入
IO
)和整数
Maybe Int
),我们最终得到了类似
IO(Maybe Int)
的类型。这些类型在Monad转换器下表达得最好,即
maybetio Int
,它们也可以很好地充当
Alternative
类成员

Haskell为这些情况提供了极好的解决方案,因此我们可以像这样处理相同的问题

import Control.Monad (msum)
import Control.Monad.Trans.Maybe
import Control.Monad.Trans (lift)
import Text.Read (readMaybe)

lp_reqInt :: MaybeT IO Int
lp_reqInt = msum . repeat $ (lift . putStrLn) "Enter an integer.." >>
                            (MaybeT $ readMaybe <$> getLine)

您的
let
语句需要
in
关键字,因为它不在
do
块中。@4castle您将
放在
关键字中的确切位置?in
中的
将在
返回之前。然而,
case
在这里比
if
更好,因为您可以对
readMaybe input1
的结果进行模式匹配。您的
let
语句需要
in
关键字,因为它不在
do
块中。@4castle您将
放在
关键字中的确切位置?将
放在
关键字中在
返回之前向右走
。但是,
case
在这里比
if
更好,因为您可以对
readMaybe input1
的结果进行模式匹配。