注意:camccann的答案比我的好,但是我的方法稍有不同,並給出了一個如何評估狀態monad的例子,所以我將它留在這裏作爲參考。
我們就可以開始嘗試通過除去getAverage
類型簽名和參數(c
),以找出問題不會出現在函數:
getAverage s=get >>= \s0 -> let (x,s1) =media s s0
in put s1 >> return x
這還不編譯,因爲我們試圖put
東西沒有正確的類型:s1
是Double
,而不是MyState
。這是很容易可以解決的:
getAverage s=get >>= \s0 -> let [email protected](x,_) =media s s0
in put s1 >> return x
我們也可以離開let
格局不變,只是說put (x,s1)
:我做這種方式,而不是讓我們s1
具有相同類型爲s0
。
這個編譯,所以現在我們可以修復類型簽名。如果我們問GHCI的類型,它返回如下:
getAverage :: (Fractional t, MonadState (t, t) m) => t -> m t
Double
是Fractional
一個實例,State MyState
是MonadState (Double, Double)
一個實例,所以我們可以用非常相似,你的原始類型的東西getAverage
:
getAverage :: Double -> State MyState Double
該功能並沒有真正「得到」平均:它更新它添加一個新的值之後,讓我們適當將其重命名:
updateAverage :: Double -> State MyState Double
updateAverage s=get >>= \s0 -> let [email protected](x,_) =media s s0
in put s1 >> return x
現在,我們可以定義一個getAverages
函數,它的Double
個列表,運行他們通過updateAverage
,並在每個步驟返回中間平均數的列表:我們期望什麼
getAverages :: [Double] -> [Double]
getAverages ss = evalState (mapM updateAverage ss) (0, 0)
這確實:
*Main> getAverages [1..10]
[1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5]
需要注意的是做什麼用State
單子有用你總是不得不使用evalState
(或密切相關的runState
和execState
)。
你應該粘貼錯誤是什麼。 – 2010-07-30 17:10:38
你在命令行輸入什麼命令來運行'getAverage'函數? – 2014-05-12 23:57:04