jhe*_*dus 3 haskell scala state-monad
据我所知,在Haskell中,State monad很有用,因为没有可变变量(除非我们在IO monad中).
但是,与Scala有什么关系?State Monad是否适用于存在可变变量的语言?
在某种意义上,State Monad允许的是在Monad上下文中使用一些局部可变变量.例如这里:
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
Run Code Online (Sandbox Code Playgroud)
在Scala中使用可变变量,这段代码会更简单(3-4行).就像是:
case class Tr (...)
case class LTr (...)
def labelTree = (... recursive call ... )
哪里labelTree使用本地可变变量来存储标签的当前状态.
我真的没有看到State Monads在Scala中的用处.为什么有人会在Scala中使用State Monad?它有什么好的用例吗?
我可以想象唯一的用例如果有状态计算是复杂的并且由几个State Monads组成,但是在那一点上我不确定使用State Monad与普通的旧函数式编程和显式参数传递相比是多么有用(相反隐式参数传递,这是状态Monad是什么).
在Haskell中编写有状态操作时,有一种习惯用法,即动作只需要知道完成任务所需的最小状态,然后每个动作都会缩放为复合"全局状态".例如:
import Control.Lens
import Control.Monad.Trans.State
succInt :: StateT Int IO String
succInt = do
modify succ
return "Incr an Int!"
succChar :: StateT Char IO String
succChar = do
modify succ
return "Incr a Char!"
type GlobalState = (Char,[Int])
composite :: StateT GlobalState IO (String,String)
composite = do
r1 <- zoom _1 succChar
r2 <- zoom (_2.traversed) succInt
return (r1,r2)
Run Code Online (Sandbox Code Playgroud)
如果我们执行这样的示例:
ghci> runStateT composite ('a',[1,5,7])
Run Code Online (Sandbox Code Playgroud)
结果是
(("Incr a Char!","Incr an Int!Incr an Int!Incr an Int!"),('b',[2,6,8]))
Run Code Online (Sandbox Code Playgroud)
我认为通过可变变量将状态"缩放"到更大的状态将更难实现.
| 归档时间: |
|
| 查看次数: |
461 次 |
| 最近记录: |