Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.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 如何在递归IO操作中使用累加器_Haskell_Io Monad - Fatal编程技术网

Haskell 如何在递归IO操作中使用累加器

Haskell 如何在递归IO操作中使用累加器,haskell,io-monad,Haskell,Io Monad,我有以下问题: 我想逐行读取文件,然后将这些行写入另一个文件。但是,我想返回行数 因此,在纯函数中,我将使用如下累加器: function parameters=method 0 ...... method accu {end case scenario} =accu method accu {not end case} = accu+1 //and other stuff main :: IO () main

我有以下问题:

我想逐行读取文件,然后将这些行写入另一个文件。但是,我想返回行数

因此,在纯函数中,我将使用如下累加器:

function parameters=method 0 ......
                    method accu  {end case scenario} =accu
                    method accu  {not end case} = accu+1 //and other stuff
main :: IO ()
main = do
  inHandle <- openFile "in.txt" ReadMode
  outHandle <- openFile "out.txt" WriteMode
  count <- loop inHandle outHandle 0
  hClose inHandle
  hClose outHandle
  putStrLn (show count)    -- could just write @print count@
如何在不使用其他函数的情况下在do块中实现相同的功能

具体例子

module Main where 

    import System.IO
    import Data.Char(toUpper)


    main::IO()
    main=do
        let inHandle=openFile "in.txt" ReadMode
        let outHandle=openFile "out.txt" WriteMode
        inHandle>>= \a ->outHandle>>= \b ->loop a b 0>>=print . show 


    loop::Handle->Handle->Int->IO Int
    loop inh outh cnt=hIsEOF inh>>= \l ->if l then return elem
                                        else
                                            do
                                                hGetLine inh>>=hPutStrLn outh
                                                loop inh outh (cnt+1)
编辑

循环
获取其参数的方式进行重构

p.S.2(在K.A.布尔的彻底回应之后)

I.我真正想要实现的是
main
方法的最后一个表达式。我想执行多个
IO操作
s并将其结果绑定到一个方法。具体而言:

inHandle>>= \a ->outHandle>>= \b ->loop a b 0>>=print . show
在这种情况下,我不理解的是:

如果将
inHandle>=
提供给
\a->
,然后将结果传递给
..>=\b
,是否在
\b
中关闭外部范围内的变量

如果不是,它不应该是
>=\a->..>=\ab
?内部范围不应该包含与外部范围的结果相对应的参数吗

在助手方法中消除do

我想知道的是,是否有一种方法可以将多个动作粘合在一起,而不必将它们放在
do
块中

就我而言:

loop::Handle->Handle->Int->IO Int
        loop inh outh cnt=hIsEOF inh>>= \l ->if l then return elem
                                            else
                                                do
                                                    hGetLine inh>>=hPutStrLn outh
                                                    loop inh outh (cnt+1)
难道我不能说:


如果。。。然后…

否则

hPutStrLn=看起来您最后一个问题的答案仍然让您感到困惑

tl;dr:停止使用
>=
=首先,我建议避免使用代码>=
=这看起来你上一个问题的答案仍然让你感到困惑

tl;dr:停止使用
>=
=首先,我建议避免使用代码>=
=为什么不想使用其他函数?在Haskell中,这是执行类似操作的“正常”方式。您在使用
let inHandle=(=使用
loop::Handle->Handle->Int->IO Int
作为类型,并将0作为初始整数累加器传递。在递归调用中,您可以使用
loop ioIn ioOut(accu+1)
你不能用
>=
>=
创建一个新的绑定,因为它只是一个函数(所以它的参数必须已经存在)。在
do
块中,你只能用
let
inHandle>=\a->outHandle>=\b->loop a b 0>=print创建一个新绑定。show
实际上是
inHandle>=(\a->outHandle>>=(\b->loop a b 0>>=(print.show))
因此,当我们到达
(print.show)
时,
b
a
都在范围内——第二个(
\b->…
)lambda嵌套在第一个(
\a->…
)lambda。为什么不想使用另一个函数?在Haskell中,这是执行类似操作的“正常”方式。在
let inHandle=(=改用
loop::Handle->Handle->Int->IO Int
作为类型,并将0作为初始整数累加器传递。在递归调用中,您可以使用
loop ioIn ioOut(accu+1)
您无法使用
>=
=
创建新绑定,因为它只是一个函数(因此它的参数必须已经存在)。在
do
块中,您只能使用
let
=\a->outHandle>=\b->loop a b 0>>=print创建一个新绑定。show
实际上是
inHandle>=(\a->outHandle>=(\b->loop a b 0>=(print.show))
所以当我们到达
(print.show)时
b
a
都在范围内——第二个(
\b->…
)lambda嵌套在第一个(
\a->…
)lambda中。
IORef
对于初学者来说比
StateT
imo更容易处理,但如果不是这样的话,这是一个很好的回答,我发现“是一个IO操作”语言极为混乱,即使直接限定词是“配方”。我认为只要马上说“是IO操作配方”就清楚多了。对于从do符号开始,我非常同意。(只是想了一件事——对单子使用“Doable”作为“Mappable”的平行词怎么样对于函子…?当然是给新手的提示,而不是一个严肃的命名建议。)续。因此,它将读作“(1)在Haskell中,
IO a
类型的任何值都是I/O操作配方。该配方描述了一些可以执行的I/O操作,以执行一些实际的输入/输出,从而产生一些
a
类型的值。因此,
IO String
类型的值是一个I/O操作配方,如果执行,将执行这些输入/输出a操作并生成一个类型为
String
的值,因此…(3)可以使用do符号将多个I/O操作配方组合成一个组合I/O操作配方“…供您考虑:”(尚未阅读其余内容…(参见Conor McBride的a,带图片).但是,在阅读了你更多的优秀答案后,我发现这一变化需要相当广泛的重写,所以,没关系。:(澄清一下:“行动”让我感到困惑,因为对我来说,“行动”是已经在执行的东西,已经在执行了)对于初学者来说,
IORef
StateT
imo更容易处理,但除此之外,这是一个很好的回答。我发现“是一个IO操作”的语言非常令人困惑,即使是即时操作
myAction :: IO ()
myAction = do
  putStrLn "Your name?"
  x <- getLine
  let stars = "***"
  putStrLn (stars ++ x ++ stars)
import System.IO

myAction :: IO ()
myAction = do
  inHandle <- openFile "in.txt" ReadMode
  outHandle <- openFile "out.txt" WriteMode
  loop inHandle outHandle
  hClose outHandle
  hClose inHandle
> :t openFile "in.txt" ReadMode
openFile "in.txt" ReadMode :: IO Handle
>
let inHandle = openFile "in.txt" ReadMode
inHandle <- openFile "in.txt" ReadMode
loop :: Handle -> Handle -> IO ()
loop inHandle outHandle = do
  end <- hIsEOF inHandle
  if end
    then return ()
    else do
      line <- hGetLine inHandle
      hPutStrLn outHandle line
      loop inHandle outHandle
end <- hIsEOF inHandle
main :: IO ()
main = myAction
import System.IO

main :: IO ()
main = do
  inHandle <- openFile "in.txt" ReadMode
  outHandle <- openFile "out.txt" WriteMode
  loop inHandle outHandle
  hClose inHandle
  hClose outHandle

loop :: Handle -> Handle -> IO ()
loop inHandle outHandle = do
  end <- hIsEOF inHandle
  if end
    then return ()
    else do
      line <- hGetLine inHandle
      hPutStrLn outHandle line
      loop inHandle outHandle
end <- hIsEOF inHandle
if end
  then ...
if hIsEOF inHandle
  then ...
loop inHandle outHandle
count <- loop inHandle outHandle 0
main :: IO ()
main = do
  inHandle <- openFile "in.txt" ReadMode
  outHandle <- openFile "out.txt" WriteMode
  count <- loop inHandle outHandle 0
  hClose inHandle
  hClose outHandle
  putStrLn (show count)    -- could just write @print count@
loop :: Handle -> Handle -> Int -> IO Int
loop inHandle outHandle count = do
  end <- hIsEOF inHandle
  if end
    then return count
    else do
      line <- hGetLine inHandle
      hPutStrLn outHandle line
      loop inHandle outHandle (count + 1)
import System.IO

main :: IO ()
main = do
  inHandle <- openFile "in.txt" ReadMode
  outHandle <- openFile "out.txt" WriteMode
  count <- loop inHandle outHandle 0
  hClose inHandle
  hClose outHandle
  putStrLn (show count)    -- could just write @print count@

loop :: Handle -> Handle -> Int -> IO Int
loop inHandle outHandle count = do
  end <- hIsEOF inHandle
  if end
    then return count
    else do
      line <- hGetLine inHandle
      hPutStrLn outHandle line
      loop inHandle outHandle (count + 1)
import Control.Monad.Loops
import System.IO
main :: IO ()
main =
  withFile "in.txt" ReadMode $ \inHandle ->
  withFile "out.txt" WriteMode $ \outHandle ->
    whileM_ (not <$> hIsEOF inHandle) $ do
      line <- hGetLine inHandle
      hPutStrLn outHandle line
import Control.Monad.State
import Control.Monad.Loops
import System.IO
main :: IO ()
main = do
  n <- withFile "in.txt" ReadMode $ \inHandle ->
       withFile "out.txt" WriteMode $ \outHandle ->
       flip execStateT 0 $
         whileM_ (not <$> liftIO (hIsEOF inHandle)) $ do
           line <- liftIO (hGetLine inHandle)
           liftIO (hPutStrLn outHandle line)
           modify succ
  print n
else do
  line <- hGetLine inHandle
  hPutStrLn outHandle line
  loop inHandle outHandle (count + 1)
else hGetLine inHandle >>= hPutStrLn outHandle >> loop inHandle outHandle (count + 1)