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