State monad haskell?

Up vote 2 down vote favorite share g+ share fb share tw.

I want to write a function for calculating the average using the State Monad in haskell this is the code I wrote as far import Control.Monad. State type MyState = (Double,Double) media s (a,n)= ((a*n+s)/(n+1),n+1) getAverage:: Double ->State MyState s1-> Double getAverage s c=get >>= \s0 -> let (x,s1) =media s s0 in put s1 >> return x I got this error when compile in GHCI, and I stuck there can you help me to understand what is wrong, thank you in advance haskell monads state-monad link|improve this question edited Apr 22 '11 at 18:15Don Stewart45.5k9133195 asked Jul 30 '10 at 17:06arpho1094 31% accept rate.

4 You should paste what the error was. – Josh Lee Jul 30 '10 at 17:10.

The code you provided gives this error: Couldn't match expected type `Double' against inferred type `m Double' In the expression: get >>= \ s0 -> let (x, s1) = ... in put s1 >> return x In the definition of `getAverage': getAverage s c = get >>= \ s0 -> let ... in put s1 >> return x All this means is that the type resulting from the expression ("inferred") disagrees with the type signature ("expected"). In this case, getAverage operates in the State monad, so it's the type signature that's incorrect, as it can't evaluate to a non-monadic type. Your code has other problems besides that, however, and won't compile even after fixing that particular issue.

First a few stylistic issues to make it more readable: getAverage has an unused parameter, which is supposedly a value in the State monad, which doesn't really make sense anyway. Using the do notation is usually clearer than using (>>=) and lambdas, especially for something like State. The indentation of the second line is confusing, since the in goes with the let that's inside the lambda.

Making those changes we have this: getAverage s = do s0 MyState -> MyState media s (a, n) = ((a * n + s) / (n + 1), n + 1) getAverage:: Double -> State MyState Double getAverage s = do modify (media s) fmap fst get We can also note that getAverage is kind of doing two different things, and split it into separate functions: updateAverage:: Double -> State MyState () updateAverage s = modify (media s) currentAverage :: State MyState Double currentAverage = fmap fst get getAverage:: Double -> State MyState Double getAverage s = updateAverage s >> currentAverage Edit: And since I forgot about the minor detail of actually getting the results back out of the monad, replacing updateAverage with getAverage in Travis Brown's getAverages function will let it work on my code above.

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 Doubles, 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).

That's the tell-tale sign that this doesn't need a monad, and thus your version can be rewritten as updateAverage s = modify (media s) *> (fst get). Similarly, mapM can be generalized as traverse, which does the same thing for any Applicative through any Traversable. – C.

A. McCann Jul 30 '10 at 18:21.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions