Jor*_*dan 14 monads haskell functional-programming
我的程序的状态包含三个值,a,b,和c,类型A,B和C.不同的功能需要访问不同的值.我想使用Statemonad 编写函数,以便每个函数只能访问它需要访问的状态段.
我有以下四种类型的功能:
f :: State (A, B, C) x
g :: y -> State (A, B) x
h :: y -> State (B, C) x
i :: y -> State (A, C) x
Run Code Online (Sandbox Code Playgroud)
以下是我打电话的g内容f:
f = do
-- some stuff
-- y is bound to an expression somewhere in here
-- more stuff
x <- g' y
-- even more stuff
where g' y = do
(a, b, c) <- get
let (x, (a', b')) = runState (g y) (a, b)
put (a', b', c)
return x
Run Code Online (Sandbox Code Playgroud)
这个g'功能是一个丑陋的样板,它只能弥补类型(A, B, C)和之间的差距(A, B).它基本上是一个g以3元组状态运行的版本,但保留第3个元组项目不变.我正在寻找一种f没有该样板的写法.也许是这样的:
f = do
-- stuff
x <- convert (0,1,2) (g y)
-- more stuff
Run Code Online (Sandbox Code Playgroud)
其中convert (0,1,2)将类型的计算转换State (a, b) x为类型State (a, b, c) x.同样,对于所有类型的a,b,c,d:
convert (2,0,1)转换State (c,a) x为State (a,b,c) xconvert (0,1)转换State b x为State (a,b) xconvert (0,2,1,0)转换State (c,b) x为State (a,b,c,d) x我的问题:
f和g,无论是F⊆ G或G⊆ F,这里F是一组由所需的状态值的f和G是一组由所需的状态值g.我错了吗?(请注意,我的示例不满足此属性.例如,G= {a, b}和H= {b, c}.两者都不是另一个的子集.)(我提到的功能看起来像这样.)
convert_0_1_2 :: State (a, b) x -> State (a, b, c) x
convert_0_1_2 f = do
(a, b, c) <- get
let (x, (a', b')) = runState f (a, b)
put (a', b', c)
return x
convert_0_2_1_0 :: State (c, b) x -> State (a, b, c, d) x
convert_0_2_1_0 f = do
(a, b, c, d) <- get
let (x, (b', c')) = runState f (b, c)
put (a, b', c', d)
return x
Run Code Online (Sandbox Code Playgroud)
您可以使用zoom from lens-family或lens包中的tuple-lenses包来实现:简化类型zoom是:
zoom :: Lens' s a -> State a x -> State s x
Run Code Online (Sandbox Code Playgroud)
因此,zoom使用较小的状态运行计算.将Lens用于指定较小的状态的位置a的较大的状态内s.
有了这两个包,可以运行g,h且i如下:
f :: State (A,B,C) x
f = do
zoom _12 g -- _12 :: Lens' (A,B,C) (A,B)
zoom _23 h -- _23 :: Lens' (A,B,C) (B,C)
zoom _13 i -- _13 :: Lens' (A,B,C) (A,C)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
231 次 |
| 最近记录: |