2014-10-29 161 views
1

我需要在一排,其中第一個確定的最後2個1是否將被計算或不生成3個隨機的值:Haskell的隨機發生器:鏈生成的隨機值

randomEnemy :: World -> World 
randomEnemy [email protected](World{enemies=e, rndGen}) = doR0 (randomR (0, 10) rndGen) 
    where 
     doR0 (a, g) = 
      if a <= 1 
       then doR1 (randomR (-562, 562) g) 
       else world 
     doR1 (a, g) = doR2 (a, randomR (-288, 288) g) 
     doR2 (a, (b, g)) = world { enemies = e ++ [Enemy (a,b) (0,0)], 
            rndGen=g } 

然而,這不是工作,我不知道爲什麼。它應該簡單地計算一個介於0和10之間的隨機值,它決定了是否應該生成一個隨機敵人,如果是這樣,它應該爲該位置計算更多的隨機數,否則返回當前遊戲狀態不變。

雖然如果我改變doR0第一次調用doR1它的工作,這讓我完全一無所知..

如果有人可以幫助我在這個它會非常感謝!

此致敬禮, Skyfe。

編輯:它拋出的錯誤(sumarized):

No instance for (Ord a0) arising from a use of `DoR0` 
The type variable `a0 is ambigious` 
... 
No instance for (Random a0) arising from a use of `RandomR` 
The type variable `a0` is ambigious 
+2

這是我真的會推薦使用'MonadRandom'軟件包的觀點。另外,在'where'之前沒有40列空白的情況下,你的代碼會更加可讀。 – bheklilr 2014-10-29 15:46:33

+0

我想我知道你的問題。如果'a <= 1',你每次都會在'doR0'中返回同一個世界,但是你有一個新的StdGen可以更新它。如果我簡單地將else子句改爲'world {rndGen = g}',那麼它會產生很多敵人。 – bheklilr 2014-10-29 16:06:34

+0

感謝您的評論。我嘗試過,但仍然會報錯。即使我把:doR0(a,g)= doR1(randomR(-562,562)g)它仍然會拋出一個錯誤,如果我直接把它放在randomEnemy函數中,它不會拋出錯誤,但它會如果我通過doR0調用它。 – user2999349 2014-10-29 16:12:21

回答

2

你的問題來自GHC不能夠找出randomR (0, 10) rndGen應該返回什麼類型。您對此值的唯一約束是您需要能夠將其與1進行比較,因此它需要滿足Random,NumOrd類型類。另一個doRN工作是因爲您生成的隨機值被放置到具有指定具體類型的數據結構中,因此編譯器可以推斷出其他用途返回的值類型爲randomR。您可以通過指定它需要在幾個地方返回Int解決這個問題,最乾淨的是通過添加型簽名的(Int, StdGen) -> WorlddoR0,所以現在的編譯器可以推斷randomR (0, 10) rndGen,因爲它是由doR0消耗返回(Int, StdGen)類型的值。