关于monad变压器:Haskell更改IO功能中的状态

Haskell Change state in IO function

我正在尝试更新IO功能中的记录。我试图使用状态单子没有成功。我在某处看到一条评论,认为有可能用state政府解决类似的问题。是否可以使用State-monad来执行此操作,还是必须使用monad变压器?如果是这样的话,我将为您做一个简短的解释,不胜感激。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{-# LANGUAGE GADTs #-}

data CarState = CS {color :: String  }

initState :: CarState
initState = CS {color ="white"}


data Car where
   ChangeColor :: String  -> Car

func :: Car -> CarState -> IO ()
func (ChangeColor col) cs = do

     putStrLn ("car is" ++ show(color cs))

     -- Change state here somehow
    --  colorChange"green"

     putStrLn ("car is now" ++ show(color cs))


main :: IO ()
main = func (ChangeColor"green") initState

colorChange :: String -> MyState CarState String
colorChange col = do
     cs <- get
     put $ cs {color = col}
     return col


data MyState s a = St (s -> (a,s))

runSt :: MyState s a -> s -> (a,s)
runSt (St f) s = f s

evalSt :: MyState s a -> s -> a
evalSt act = fst . runSt act

get :: MyState s s
get = St $ \\s -> (s,s)

put :: s -> MyState s ()
put s = St $ \\_ -> ((),s)

instance Monad (MyState s) where
   return x       = St $ \\s -> (x,s)
   (St m) >>= k = St $ \\s_1 -> let (a, s_2) = m s_1
                               St k_m = k a
                           in k_m s_2

instance Functor (MyState s) where
    fmap f (St g) = St $ \\s0 -> let (a, s1) = g s0
                                in (f a, s1)

instance Applicative (MyState s) where
    pure a = St (\\s -> (a,s))
    (<*>) (St sa) (St sb) = St (\\s0 -> let (fn, s1) = sa s0
                                       (a,  s2) = sb s1  
                                   in (fn a, s2))

在Haskell中,您永远无法通过任何机制对数据进行适当的突变。完全是1

在Haskell中对状态更新进行建模的方式是产生一个新值,该新值与旧值相同,除了" updated "位。

例如,您要执行的操作将这样表示:

1
2
func :: Car -> CarState -> CarState
func (ChangeColor c) cs = cs { color = c }

1好吧,从技术上讲,您有时可以,但是它仅适用于预先安排为可变的数据,并且通常很麻烦。不是编写程序的正常方法。