Note: camccann's answer is better than mine, but mine takes a slightly different approach and gives an example of how to evaluate the state monad, so I'm leaving it here for reference.
We can start trying to figure out the problem by removing the type signature for getAverage
and the argument (c
) that doesn't appear in the function:
getAverage s=get >>= \s0 -> let (x,s1) =media s s0
in put s1 >> return x
This still doesn't compile, because we're trying to put
something that doesn't have the right type: s1
is a Double
, not a MyState
. This is easily fixable:
getAverage s=get >>= \s0 -> let s1@(x,_) =media s s0
in put s1 >> return x
We could also leave the let
pattern unchanged and just say put (x,s1)
: I'm doing it this way instead so that our s1
has the same type as s0
.
This compiles, so now we can fix the type signature. If we ask GHCi for the type, it returns the following:
getAverage :: (Fractional t, MonadState (t, t) m) => t -> m t
Double
is an instance of Fractional
, and State MyState
is an instance of MonadState (Double, Double)
, so we can use something very similar to your original type for getAverage
:
getAverage :: Double -> State MyState Double
This function doesn't really "get" the average: it updates it after adding a new value, so let's rename it appropriately:
updateAverage :: Double -> State MyState Double
updateAverage s=get >>= \s0 -> let s1@(x,_) =media s s0
in put s1 >> return x
Now we can define a getAverages
function that takes a list of Double
s, runs them through updateAverage
, and returns a list of the intermediate averages at each step:
getAverages :: [Double] -> [Double]
getAverages ss = evalState (mapM updateAverage ss) (0, 0)
This does what we'd expect:
*Main> getAverages [1..10]
[1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5]
Note that to do anything useful with the State
monad you'll always have to use evalState
(or the closely related runState
and execState
).