Creating / processing Monad.State lists?

I am just studying haskell and I am sure that there is an elegant solution to the following problem. Given a function f that returns a stateful calculation

f :: (Num a) => a -> a -> State [a] a fxy = modify ((2*x):) >> return (x+y) -- state and value are modified based on the passed values 

I am looking for the cleanest way to generate multiple State from a given recursively (as shown below). One solution I came up with is the following

 g :: (Num a) => [a] -> (a, [a]) -> [(a,[a])] g [] _ = [] g (x:xs) aa@ (a,b) = (new : next) where new = runState (fxa) b -- here the old value a is required! next = g xs aa 

but I think something like

 g :: [a] -> [State [a] a] 

should be possible and cleaner? I was not able to do this and get errors from StateT that I cannot understand.

Thanks!

Background: code is a simplification of the parts of the graph generator that I write, where the state is the current adjacency vector. For each node, several edges can be created, and therefore several states are required that represent different (partial) graphs.

Edit: (Try it) Description in words of the above function gx (y, s) in words:

For a given list of values โ€‹โ€‹of x , a single value of y and state s , derive recursively for each x_i into x new value and state from (y,s) , the calculation function f x_i y specified by the state function, and return the result as a list.

Edit 2: Example output:

  g [1,2,3] (4,[2,3,4]) == [(5,[10,2,3,4]),(6,[12,2,3,4]),(7,[14,2,3,4])] 
+4
source share
1 answer

Here are a few iterative changes to your g function. Hope this is what you were looking for because I'm not sure I fully understand what you were trying to achieve:

Original g:

 g :: Num a => [a] -> a -> [a] -> [(a,[a])] g [] _ _ = [] g (x:xs) ab = new : next where new = runState (f (hxa)) b -- here the old value a is required! next = g xs ab 

Point free:

 g1 :: Num a => [a] -> a -> [a] -> [(a,[a])] g1 xs ab = map (($ b) . runState . f . (`h` a)) $ xs 

Fault tolerance for ETA reduction:

 g2 :: Num a => [a] -> a -> [a] -> [(a,[a])] g2 ba = map (($ b) . runState . f . (`h` a)) 

Without application ($ b) . runState ($ b) . runState (no additional argument [a] is needed since we do not use state calculations):

 g3 :: Num a => a -> [a] -> [State [a] a] g3 a = map (f . (`h` a)) 

The display can also be written:

 map f . map (`h` a) 

and then you can take

  map (\`h\` a) 

part from another place.

This gives you something similar to the type you want for g , and of course changes the semantics (since this type is still not used for input)

+3
source

Source: https://habr.com/ru/post/1380655/


All Articles