我有曖昧類型在Haskell麻煩。我開始了以下內容:哈斯克爾 - 模糊的類型變量
module GameState
(GameState(..)
, GameStateMonad
, module Control.Monad.Trans
, module Control.Monad.Trans.State.Lazy
, Blank(..)
) where
import Control.Monad.Trans
import Control.Monad.Trans.State.Lazy
type GameStateMonad a b = StateT a IO b
class GameState a where
update :: Double -> GameStateMonad a()
update deltaTime = return()
draw :: GameStateMonad a()
draw = return()
getNextState :: GameState b => GameStateMonad a (Maybe b)
getNextState = return Nothing
isStateFinished :: GameStateMonad a Bool
isStateFinished = return True
-- This is just a dummy data and instance declaration to demonstrate the error
data Blank = Blank
instance GameState Blank
然後,當我嘗試運行ghci的以下內容:
runStateT getNextState Blank
我得到:
Ambiguous type variable `b0' in the constraint:
(GameState b0) arising from a use of `getNextState'
Probable fix: add a type signature that fixes these type variable(s)
...
我還以爲是說我的默認實施getNextState功能沒有指定具體的類型,所以我嘗試了以下內容:
getNextState :: GameState b => GameStateMonad a (Maybe b)
getNextState = return (Nothing :: Maybe Blank)
不幸的是我在編譯時得到這個錯誤:
Could not deduce (b ~ Blank)
from the context (GameState a)
bound by the class declaration for `GameState'
at GameState.hs:(14,1)-(25,33)
or from (GameState b)
bound by the type signature for
getNextState :: GameState b => GameStateMonad a (Maybe b)
at GameState.hs:22:5-50
`b' is a rigid type variable bound by
the type signature for
getNextState :: GameState b => GameStateMonad a (Maybe b)
at GameState.hs:22:5
...
但我發現,添加一個類型簽名時,我打電話GETNEXT狀態允許代碼運行:
runStateT (getNextState :: GameStateMonad Blank (Maybe Blank)) Blank
很不幸,這阻止我從使通用代碼來處理遊戲狀態。這對我來說也沒有多大意義。如果你必須在返回一個顯式類型時返回一個多態類型有什麼意義?原來的問題也讓我很困惑,因爲我可以做一個功能如下:
test :: Num a => Maybe a
test = Nothing
而且沒有問題運行它。難道這不應該抱怨我的原始代碼這樣的模棱兩可的類型嗎?也使返回值時,一個明確的類型,我不能編譯它,像以前一樣:
test :: Num a => Maybe a
test = Nothing :: Maybe Int
我不明白爲什麼這是一個問題。 Int是Num類型的一個實例,所以函數的類型是正確的。
我有四個問題:
返回類型類的元素時,會導致編譯錯誤,爲什麼給一個明確的類型?
爲什麼返回getNextState內部曖昧的可能值導致一個錯誤,但內部測試不?
爲什麼會出現沒有我調用返回的多態數據的函數這個錯誤,因爲解釋here?
在the link above,得到的答覆提到,「[你得到這個錯誤,因爲你有一些產生多態的結果,然後將一個函數,需要一個多態參數這一結果,使得中間值的類型未知」。這是否意味着返回多態結果的函數實質上是無用的?
謝謝。
'a'是類參數,因此您不應該對其進行量化,或者添加'GameState a'約束。 –
'這個函數的實現不能決定a和b是什麼......因爲它是由主叫方決定的' 這使事情變得更有意義。謝謝。 我正在製作gamestate typeclass,因爲我想要一個可以使用任何使用通用接口的遊戲狀態運行遊戲的函數。這樣我可以遞歸調用該函數來獲得一堆遊戲狀態。我對Haskell沒有多少經驗,所以我不確定實現這個目標的最佳選擇是什麼,但是類型類似於合適。 –
@TerranceNiechciol:正如我所說的,從簡單的ADT開始。而不是'數據StateA = ...;數據狀態B = ...;'+實例做'數據狀態=狀態A ... | StateB ...'而不是。只有在這個不足時才嘗試使用類型分類方法。 –