Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.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 用foldM和State编写一个简单函数_Haskell - Fatal编程技术网

Haskell 用foldM和State编写一个简单函数

Haskell 用foldM和State编写一个简单函数,haskell,Haskell,我试图编写一个小函数,它基本上遍历一系列问题,对于每个问题,提示符将等待用户的响应,如果答案正确,则在分数上加1,如果答案错误,则不做任何操作 我认为如果我只需要记录分数,使用foldM就足够了,但是我还想打印每个问题在列表中的位置,比如“问题1:”等等 使用状态单子有助于跟踪分数和位置吗? 除此之外,我很想和国家队练习 以下是当前代码: 每个问题都是一个包含字符串和答案的元组 import Control.Monad import Control.Concurrent import Syste

我试图编写一个小函数,它基本上遍历一系列问题,对于每个问题,提示符将等待用户的响应,如果答案正确,则在分数上加1,如果答案错误,则不做任何操作

我认为如果我只需要记录分数,使用foldM就足够了,但是我还想打印每个问题在列表中的位置,比如“问题1:”等等

使用状态单子有助于跟踪分数和位置吗? 除此之外,我很想和国家队练习

以下是当前代码:

每个问题都是一个包含字符串和答案的元组

import Control.Monad
import Control.Concurrent
import System.Exit


qs =
    [( "question"
     ,["1"]            --number of the correct answer, from 1 to 4
    ]

main =
    putStrLn "Type \"init\" to begin" >>
    getLine >>= \l -> case l of
        "init" -> act
        _      -> main

act :: IO ()
act =
    let score = foldM (
        \acc (q,a) ->
        putStrLn q >>
        getLine >>= \l ->
        if (l `elem` a)
            then putStrLn "CORRECT!"    >>
                 threadDelay (2 * 10^6) >>
                 acc >>= \a -> a + 1
            else putStrLn "WRONG!"      >>
                 threadDelay (2 * 10^6) >>
                 acc
    ) 0 qs
    in  putStrLn $ "Score: " ++ score >>
    if (score > 18)
        then putStrLn "Bravo!"    >>
        else putStrLn "Not enough!" >>
    putStrLn "Type \"1\" to restart, anything else to quit" >>
    getLine >> \l -> case l of
        "1" -> act
        _   -> exitSuccess

如果您自己提取迭代函数,则可以简化事情:

import Control.Monad

go score (question,answer) = do
  putStr $ question ++ "? "
  response <- getLine
  if response /= answer
    then do putStrLn "Wrong!"
            return score
    else do putStrLn "Right!"
            return (score+1)

questions = [ ("1+1=", "2"), ("2+2","4"), ("What is your favorite color", "\n") ]

doit = foldM go 0 questions
import-Control.Monad
去得分(问题、答案)=去做
putStr$question++“?”

响应这里有一个示例,使用
StateT
来同时考虑
状态
IO

module Main where

import Control.Monad.State

type Question = (String,String)
type Questions = [Question]
type Score = Int
type Game = StateT Score IO ()  -- combine State and IO effects

play :: Question -> Game
play (question,answer) = do
  liftIO $ putStrLn question  -- IO requires using the liftIO function explicitly
  input <- liftIO $ getLine
  if answer == input
    then do
      liftIO $ putStrLn "correct!"
      modify (+1) -- add 1 to score
    else
      liftIO $ putStrLn "wrong!"
  score <- get
  liftIO $ putStrLn $ "Your score is: " ++ (show score)

questions :: Questions
questions = [("1+1=", "2"), ("What is the best programming language?", "haskell")]

main :: IO ()
main = do
  runStateT (traverse play questions) 0  -- no need for foldM since we're using State to handle the score
  putStrLn "game over"
modulemain其中
进口控制单体状态
类型问题=(字符串,字符串)
类型问题=[问题]
类型分数=整数
类型Game=StateT Score IO()--组合状态和IO效果
游戏:问题->游戏
玩(问题,回答)=做
liftIO$putStrLn问题——IO需要显式使用liftIO函数

如果没有IO,您可以使用状态进行输入。作为练习,您可以将所有代码转换为纯代码,例如,通过提供一个答案列表来替换交互式getLine。如果您想使用State和IO,您需要使用StateT(monad转换器:我建议您先编写纯版本)。
module Main where

import Control.Monad.State

type Question = (String,String)
type Questions = [Question]
type Score = Int
type Game = StateT Score IO ()  -- combine State and IO effects

play :: Question -> Game
play (question,answer) = do
  liftIO $ putStrLn question  -- IO requires using the liftIO function explicitly
  input <- liftIO $ getLine
  if answer == input
    then do
      liftIO $ putStrLn "correct!"
      modify (+1) -- add 1 to score
    else
      liftIO $ putStrLn "wrong!"
  score <- get
  liftIO $ putStrLn $ "Your score is: " ++ (show score)

questions :: Questions
questions = [("1+1=", "2"), ("What is the best programming language?", "haskell")]

main :: IO ()
main = do
  runStateT (traverse play questions) 0  -- no need for foldM since we're using State to handle the score
  putStrLn "game over"