0

以下是我就餐哲学家的代码,并产生一个编译错误,说“'do' 构造中的最后一条语句必须是一个表达式:mVar2 <- newEmptyMVar mVar3” 有人可以帮我解决这个错误并让这个程序工作吗?谢谢你

import Control.Concurrent
import Control.Concurrent.MVar
import System.Random

takefork :: Int -> forks -> IO ()
takefork n forks = takeMVar (forks!!n)

releasefork :: Int -> forks -> IO ()
releasefork n forks = putMVar (forks!!n)

philosopher :: [Int]
philosopher = [1,2,3,4,5]

forks :: [MVar] -> [Int]
forks = do
    takefork n ( philosopher - 1)
    threadDelay delay
    let delay = 100000
    takefork n philosopher
    putStrLn("Philosopher" ++ philosopher ++ "has started eating")
    releasefork n philosopher
    releasefork n ( philosopher - 1)
    ptStrLn ("Philosopher" ++ philosopher ++ "has stopped eating")
    forks

main :: IO ()
main = do
    mVar1 <- newEmptyMVar
    mVar2 <- newEmptyMVar
    mVar3 <- newEmptyMVar
    mVar4 <- newEmptyMVar
    mVar5 <- newEmptyMVar
    let mVar = [mVar1, mVar2, mVar3, mVar4, mVar5]
    sequence_ [ forkIO forks (mVar philosopher) ]
4

1 回答 1

6

你的代码有很多问题。

您报告的错误消息表明您可能混合了空格和制表符。摆脱制表符,只使用空格。


您可能编写这个程序是为了练习编写 Haskell 程序,而不是为了娱乐和盈利而运行该程序。因此,我们不想简单地为您提供一个有效的 Dining Philosophers 实现,我们希望帮助您编写您的实现。

我无法从您的代码中看出您期望它如何工作。

我将重点关注最后一行:

sequence_ [ forkIO forks (mVar philosopher) ]

sequence_ :: [IO a] -> IO ()--- 给出sequence_一个 i/o 动作列表,它(返回一个 i/o 动作)按顺序执行每个动作。从 中[...],您似乎正在尝试给它一个列表,但只有一个元素。这可能不是你的意思。

forkIO :: IO () -> IO ThreadID--- 给出forkIO一个 i/o 动作,它(返回一个 i/o 动作)启动在一个新线程中运行的 i/o 动作,给你那个线程的 id。

这里有两个问题:

  • forks是一个函数,而不是一个 i/o 动作(它甚至不是一个返回 i/o 动作的函数,尽管您可能是认真的)
  • 你给出forkIO第二个参数 ( (mVar philosopher)),但它只需要一个参数

mVar philosopher本身没有任何意义:(mVar :: [MVar a]它是一个 MVar 列表,我还没有弄清楚 MVar 应该包含什么类型)但是您将它视为一个函数,将其philosopher作为参数传递。

这时,一个灯泡在我头顶闪烁。你想forks用参数mVarphilosopher

sequence_ [ forkIO (forks mVar philosopher) ]

不过,我们仍在对单个操作进行排序。也许您希望依次调用forks每个元素?philosopher

sequence_ $ map (\n -> forkIO (forks mVar n)) philosopher

我们可以将其简化为

mapM_ (\n -> forkIO (forks mVar n)) philosopher

这与您给出的类型不匹配forks :: [MVar] -> [Int]。但这可能是错误的,因此您接下来需要修复该功能。

于 2012-05-24T19:30:00.287 回答