【问题标题】:Example of while loop in Haskell using monadsHaskell 中使用 monad 的 while 循环示例
【发布时间】:2017-02-13 21:35:05
【问题描述】:

我想使用 monad 在 haskell 中编写一个循环,但我很难理解这个概念。

在满足某些涉及 IO 操作的条件时,有人可以为我提供一个简单的 while 循环示例吗?我不想要一个抽象的例子,而是一个真正可行的具体例子。

【问题讨论】:

  • this question 有帮助吗?
  • 我已经看到了,但是有没有更简单的方法,我可以很容易地知道程序正在尝试立即计算什么。
  • 你有不能转换的命令式while循环的例子吗?
  • @Lee 说一些非常简单的事情,比如如果满足某个条件,则在更新条件的同时继续打印“已满足”。我不想要一个简单的递归,而是使用单子。

标签: loops haskell while-loop monads io-monad


【解决方案1】:

下面有一个可怕的例子。您已收到警告。

考虑伪代码:

var x = 23
while (x != 0) {
   print "x not yet 0, enter an adjustment"
   x = x + read()
}
print "x reached 0! Exiting"

这是它在 Haskell 中的逐段翻译,尽可能使用命令式风格。

import Data.IORef

main :: IO ()
main = do
   x <- newIORef (23 :: Int)
   let loop = do
          v <- readIORef x
          if v == 0
          then return ()
          else do
             putStrLn "x not yet 0, enter an adjustment"
             a <- readLn
             writeIORef x (v+a)
             loop
   loop
   putStrLn "x reached 0! Exiting"

上面确实是可怕的Haskell。它使用递归定义的loop 模拟while 循环,这还不错。但它在任何地方都使用 IO,包括用于模仿命令式可变变量。

更好的方法是删除那些IORefs。

main = do
   let loop 0 = return ()
       loop v = do
          putStrLn "x not yet 0, enter an adjustment"
          a <- readLn
          loop (v+a)
   loop 23
   putStrLn "x reached 0! Exiting"

无论如何都不是优雅的代码,但至少“while guard”现在不会做不必要的 IO。

通常,Haskell 程序员努力尽可能地将纯计算与 IO 分开。这是因为它通常会产生更好、更简单且不易出错的代码。

【讨论】:

    猜你喜欢
    • 2014-02-18
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多