Haskell 与StateT monad循环
这是一个学习StateT monad的练习。这个程序实现了莫拉的游戏。这两个玩家是电脑和一个人。该州累计计算机和玩家的分数。该程序用于函数morra的一次迭代。然而,我不知道如何循环它。我尝试了一些方法,但似乎没有任何效果Haskell 与StateT monad循环,haskell,Haskell,这是一个学习StateT monad的练习。这个程序实现了莫拉的游戏。这两个玩家是电脑和一个人。该州累计计算机和玩家的分数。该程序用于函数morra的一次迭代。然而,我不知道如何循环它。我尝试了一些方法,但似乎没有任何效果 module Morra where import Control.Monad.Trans.State.Lazy import Control.Monad.IO.Class import Data.Char (isDigit, digitToInt) import Syst
module Morra where
import Control.Monad.Trans.State.Lazy
import Control.Monad.IO.Class
import Data.Char (isDigit, digitToInt)
import System.Random (randomRIO)
import Control.Monad (when)
morra :: StateT (Int, Int) IO ()
morra = do
p <- liftIO getChar
when (isDigit p) $
do
let p' = digitToInt p
c <- liftIO $ randomRIO (1, 2)
liftIO $ putStrLn ['P',':',' ',p] --"P: " ++ p)
liftIO $ putStrLn ("C: " ++ show c)
(pt, ct) <- get
if even (c + p') then
do
liftIO $ putStrLn "Computer Wins"
put (pt, ct + 1)
else
do
liftIO $ putStrLn "Player Wins"
put (pt + 1, ct)
main :: IO ()
main = do
putStrLn "-- p is Player"
putStrLn "-- c is Computer"
putStrLn "-- Player is odds, Computer is evens."
fScore <- runStateT morra (0,0)
let personS = fst . snd $ fScore
compS = snd . snd $ fScore
putStrLn ("Person Score: " ++ show personS)
putStrLn ("Computer Score: " ++ show compS)
if personS > compS then
putStrLn "Winner is Person"
else
putStrLn "Winner is Computer"
模块Morra在哪里
导入控件.Monad.Trans.State.Lazy
导入控制.Monad.IO.Class
导入数据.Char(isDigit,DigitPoint)
导入系统随机(randomRIO)
导入控制.Monad(何时)
莫拉:StateT(Int,Int)IO()
莫拉
p你有99%的成功率。只需将main
添加到最后一个putStrLn
之后的新行中,main
将自动调用,从而有效地重新启动程序
简化代码中某些内容的一些技巧:
- 使用
::StateT s m a->s->ms
仅获取该回合的最终状态。这样,您就不需要使用let
绑定来提取分数,而是可以内联执行:(个人、公司)您的分数达到了99%。只需将main
添加到最后一个putStrLn
之后的新行中,main
将自动调用,从而有效地重新启动程序
简化代码中某些内容的一些技巧:
- 使用
::StateT s m a->s->ms
仅获取该回合的最终状态。这样,您就不需要使用let
绑定来提取分数,而是可以内联执行:(个人、公司)I replacedpI replacedp谢谢。但是我需要函数morra上的循环。main函数只运行一次。如果我将morra
放在函数末尾(与do
在when
之后对齐),则什么也不会发生。@user1897830当时,您需要将其与对齐(只缩进两个空格)。如果将其放入when中,则仅当isDigit p
为true时,它才会循环。你所说的“什么都没发生”是什么意思?它是立即退出还是卡在循环中?我只需要在isDigit p
为真时才需要它循环。也就是说,它循环直到isDigit p
为非真,然后退出。但是,当我将morra
放在中时,它只是退出并且不循环。@user1897830在其中添加一些liftIO(putStrLn“Test”)
,以查看控制流到底发生了什么。添加一个将在您键入角色时激活的角色,并告诉您该角色是什么。这样,你就可以发现它与你的期望有什么不同。我这样做了,第二次通过循环发现代码p谢谢你。但是我需要函数morra上的循环。main函数只运行一次。如果我将morra
放在函数末尾(与do
在when
之后对齐),则什么也不会发生。@user1897830当时,您需要将其与对齐(只缩进两个空格)。如果将其放入when中,则仅当isDigit p
为true时,它才会循环。你所说的“什么都没发生”是什么意思?它是立即退出还是卡在循环中?我只需要在isDigit p
为真时才需要它循环。也就是说,它循环直到isDigit p
为非真,然后退出。但是,当我将morra
放在中时,它只是退出并且不循环。@user1897830在其中添加一些liftIO(putStrLn“Test”)
,以查看控制流到底发生了什么。添加一个将在您键入角色时激活的角色,并告诉您该角色是什么。这样,你就可以发现它与你的期望有什么不同。我这样做了,发现第二次通过循环时代码p
if condition
then do
doSomethingA
doSomethingB
else someFunction $ do
doSomethingElseA
doSomethingElseB
module Morra where
import Control.Monad.Trans.State.Lazy
import Control.Monad.IO.Class
import Data.Char (isDigit, digitToInt)
import System.Random (randomRIO)
import Control.Monad (when)
morra :: StateT (Int, Int) IO ()
morra = do
p <- liftIO getLine
let p1 = head p
when (isDigit p1) $ do
let p' = digitToInt p1
c <- liftIO $ randomRIO (1, 2)
liftIO $ putStrLn ("P: " ++ p)
liftIO $ putStrLn ("C: " ++ show c)
(pt, ct) <- get
if even (c + p') then do
liftIO $ putStrLn "Computer Wins"
put (pt, ct + 1)
else do
liftIO $ putStrLn "Player Wins"
put (pt + 1, ct)
morra
main :: IO ()
main = do
putStrLn "-- p is Player"
putStrLn "-- c is Computer"
putStrLn "-- Player is odds, Computer is evens."
(personS,compS) <- execStateT morra (0,0)
putStrLn ("Person Score: " ++ show personS)
putStrLn ("Computer Score: " ++ show compS)
if personS == compS then
putStrLn "No Winner"
else if personS > compS then
putStrLn "Winner is Person"
else
putStrLn "Winner is Computer"