考虑以下(非常沉闷)游戏: - 玩家A认为1到100之间的数字. - 玩家B允许5次尝试猜测该数字.玩家A将对每个猜测做出"太大","太小"或"正确"的回应.
我想在Haskell中模拟这个,当然这很简单.但是为了让事情变得有趣,我想以玩家B不能"欺骗"的方式编写代码.这意味着两件事: - 玩家B代码不允许查看密码的正确值.播放器A代码为播放器B代码提供了一个函数,用于检查其猜测. - 不允许玩家B代码调用该函数超过五次.不知何故,播放器A代码必须保持调用函数的次数.
这在使用私有可变变量的OO语言中很容易实现.
在Haskell中,我使用IORef对其进行编码以记录调用次数.那很好,我认为我的解决方案是正确的.但我的问题是:
"如果没有IORef或者类似的话,这可以在Haskell中完成吗?是否有一个我错过的纯功能解决方案?"
这是我的Haskell代码:
import Data.IORef (newIORef, readIORef, writeIORef)
import System.Random (randomRIO)
lowest = 1
highest = 100
maxtries = 5
playerA :: IO (Int -> IO (Maybe Ordering))
playerA = do
secret <- randomRIO (lowest, highest)
print ("Secret", secret)
tries <- newIORef maxtries
return $ \ guess -> do
t <- readIORef tries
if t == 0 then
return Nothing
else do
writeIORef tries $ t - 1
return $ Just $ guess `compare` secret
playerB :: (Int -> IO (Maybe Ordering)) -> Int -> Int -> IO ()
playerB guessfunc lowbound highbound = do
let guess = (lowbound + highbound) `div` 2
response <- guessfunc guess
print (lowbound, highbound, guess, response)
case response of
Just GT -> playerB guessfunc lowbound (guess - 1)
Just LT -> playerB guessfunc (guess + 1) highbound
Just EQ -> putStrLn "Player B wins"
Nothing -> putStrLn "Player B loses"
main :: IO ()
main = do
guessfunc <- playerA
playerB guessfunc lowest highest
Run Code Online (Sandbox Code Playgroud)
lef*_*out 11
没有必要这样做IO,你也可以使用纯状态monad:
import Control.Monad.Trans.State
import System.Random (randomRIO)
maxtries = 5
playerA :: IO (Int -> State Int (Maybe Ordering))
playerA = do
secret <- randomRIO (1,100)
return $ \guess -> state $ \tries
-> if tries < maxtries then (Just $ guess`compare`secret, tries+1)
else (Nothing, tries)
playerB :: Monad m => (Int -> m (Maybe Ordering)) -> Int -> Int -> m (Maybe Int)
playerB guessfunc lowbound highbound = do
let guess = (lowbound + highbound)`div`2
response <- guessfunc guess
case response of
Just GT -> playerB guessfunc lowbound (guess - 1)
Just LT -> playerB guessfunc (guess + 1) highbound
Just EQ -> return $ Just guess
Nothing -> return Nothing
main = do
pa <- playerA
print . (`evalState`0) $ playerB pa 1 100
Run Code Online (Sandbox Code Playgroud)
请注意,playerB不知道monad是State Int.这很重要,所以她不能通过在调用之间操纵状态变量来作弊guessfunc.
| 归档时间: |
|
| 查看次数: |
176 次 |
| 最近记录: |