我明白,在Haskell中,State monad非常有用,因为没有可变变量(除非我们在IO monad中)。状态monad是否需要/有用可变(本地)变量(如Scala)的语言?
但是,斯卡拉的交易是什么? State Monad是否适用于有可变变量的语言?
从某种意义上说,所有State Monad允许的是use some local mutable variables within the Monad context。例如:
newtype Labeled anytype = Labeled (S -> (S, anytype))
instance Monad Labeled where
return contents = Labeled (\st -> (st, contents))
Labeled fst0 >>= fany1 =
Labeled $ \st0 ->
let (st1, any1) = fst0 st0
Labeled fst1 = fany1 any1
in fst1 st1
mlabel :: Tr anytype -> Lt anytype
mlabel tr = let Labeled mt = mkm tr
in snd (mt 0)
mkm :: Tr anytype -> Labeled (Lt anytype)
mkm (Lf x)
= updateState >>= \n -> return $ Lf (n,x)
mkm (Br l r)
= mkm l >>= \l' ->
mkm r >>= \r' ->
return $ (Br l' r')
updateState :: Labeled S
updateState = Labeled (\n -> ((n+1),n))
main = print $ mlabel tr1
这段代码在使用Scala中的可变变量时会更简单(3-4行)。喜欢的东西: case class Tr (...)
case class LTr (...)
def labelTree = (... recursive call ...)
其中labelTree
使用本地可变变量来存储标签的当前状态。
我真的没有看到State Monads在Scala中的用处。为什么会有人在斯卡拉使用State Monad?有没有好的用例呢?
我可以想象的唯一用例是,如果有状态计算是复杂的并且是由几个State Monads组成的,但是在那时我不确定使用State Monad与普通的旧函数式编程和显式参数传递(而不是隐含的参数传递,这是State Monad所在的)。
这可能是一个意见问题。但是有些想法:Haskell可以做可变引用(IORef,STRef等),所以你在Scala中给出的不使用状态的任何原因对于Haskell来说都是一样的。那么为什么哈斯克勒使用国家? – user2297560
我也猜测它在可变性语言中并不那么有用。也许可以使用状态monad来记录一个特定的子程序只改变几个变量的状态,但是保持状态的其余部分不变。也许这不值得付出努力,特别是如果状态monad被实现为一个函数,因此效率低于普通可变变量(至少没有优化)。 – chi
@ user2297560也许他们不想在IO monad中出于某种原因? – jhegedus