我正处于学习haskell的过程中,我确信存在以下问题的优雅解决方案。 给定函数f,返回有状态计算
f :: (Num a) => a -> a -> State [a] a
f x y = modify ((2*x):) >> return (x+y) -- state and value are modified based on the passed values
我正在寻找以递归方式从给定的一个State
生成多个g :: (Num a) => [a] -> (a, [a]) -> [(a,[a])]
g [] _ = []
g (x:xs) aa@(a,b) = (new : next)
where new = runState (f x a) b -- here the old value a is required!
next = g xs aa
的最简洁方法(如下所示)。我想出的一个解决方案是以下
g :: [a] -> [State [a] a]
但我觉得像
g x (y, s)
应该可行且更干净吗?我没有成功尝试这个并从StateT得到我无法弄清楚的错误。
谢谢!
背景:代码是我正在编写的图形生成器的一部分的简化,其中状态是当前的邻接向量。对于每个节点,可以创建多个边缘,因此需要多个状态来表示不同的(部分)图形。
编辑 :(尝试)上述函数x
中单词的描述:
对于给定的值列表y
,单个值s
和状态x_i
,为x
中的每个(y,s)
递归计算一个新值并从状态计算f x_i y
给出的 g [1,2,3] (4,[2,3,4]) == [(5,[10,2,3,4]),(6,[12,2,3,4]),(7,[14,2,3,4])]
状态,并将结果作为列表返回。
编辑2 :示例输出:
{{1}}
答案 0 :(得分:3)
以下是对g
函数的一些迭代更改。我希望这是你想要的,因为我不确定我完全理解你想要达到的目标:
你原来的g:
g :: Num a => [a] -> a -> [a] -> [(a,[a])]
g [] _ _ = []
g (x:xs) a b = new : next
where
new = runState (f (h x a)) b -- here the old value a is required!
next = g xs a b
点免费:
g1 :: Num a => [a] -> a -> [a] -> [(a,[a])]
g1 xs a b = map (($ b) . runState . f . (`h` a)) $ xs
翻转ETA还原性:
g2 :: Num a => [a] -> a -> [a] -> [(a,[a])]
g2 b a = map (($ b) . runState . f . (`h` a))
没有($ b) . runState
应用程序(因为我们不应用状态计算,所以不需要额外的[a]参数):
g3 :: Num a => a -> [a] -> [State [a] a]
g3 a = map (f . (`h` a))
那里的地图也可以写成:
map f . map (`h` a)
然后你可以拿
map (\`h\` a)
在其他地方分开。
这为您提供了类似于g
所需类型的东西,当然也改变了语义(因为该类型仍未应用于输入状态)