State monad:如何在Haskell中"打印"中间值

srg*_*hma 3 haskell

我是haskell的新手,我有以下代码

module StateTest where

import Control.Monad.State.Lazy

tick :: State Int Int
tick = do n <- get
          put (n+1)
          return n

plusOne :: Int -> Int
plusOne = execState tick

main = print $ plusOne 1
Run Code Online (Sandbox Code Playgroud)

我想在之后打印状态值put (n+1)并继续这样的计算

tick = do n <- get
          put (n+1)
          print
          return n
Run Code Online (Sandbox Code Playgroud)

整个代码如何看待这个?

Lee*_*Lee 5

如果要在状态计算中运行IO操作,可以更改tick返回a StateT Int IO Int和use 的类型liftIO.然后你可以运行它execStateT:

import Control.Monad.State.Lazy
import Control.Monad.IO.Class (liftIO)

tick :: StateT Int IO Int
tick = do n <- get
          put (n+1)
          liftIO $ print (n+1)
          return n

plusOne :: Int -> IO Int
plusOne = execStateT tick

main = plusOne 1 >> pure ()
Run Code Online (Sandbox Code Playgroud)

  • @bjornmelgaard这并不困难.为了比较,`IO(Int - > Bool)`是一个可以执行任意I/O的动作类型,然后返回一个不执行任何I/O的纯函数.因此,它永远不会打印整数:I/O在传递整数之前结束.相反,`Int - > IO Bool`首先取整数,然后执行I/O,最后返回一个布尔值.这里可以打印整数.这或多或少是在状态变换器层下发生的事情(起初确实有点难以理解 - 一个好的monad教程应该有帮助). (2认同)