管理,定相,组合monad的资源(在Scala或Haskell中)
我正在寻找资源讨论组成monad的良好实践.我最紧迫的问题是我正在编写一个系统,该系统正在使用一系列状态monad而不是不同的状态类型,似乎处理这种情况的最好方法就是创建一个大的产品类型(可能是prettied)即使第1阶段对组件B不感兴趣,第2阶段仅对组件A.1感兴趣,也包括我感兴趣的所有组件.
在这类领域编写代码时,我非常感谢能够很好地讨论替代方案.我自己的代码库是在Scala中,但我很高兴阅读有关Haskell中相同问题的讨论. 解决方法
使用StateT堆栈有点困难,因为当你写入get或put时,你正在谈论哪一层会让人感到困惑.如果你在变换器风格中使用显式堆栈,那么你必须使用一堆升降机,如果你使用mtl的基于类的方法,你会完全陷入困境.
-- using transformers explicit stack style type Z a = StateT Int (StateT String IO) a go :: Z () go = do int <- get str <- lift get replicateM int (liftIO $putStrLn str) 我们可能希望避免使用明确的产品类型的状态.由于我们最终得到了从产品状态到每个单独组件的功能,因此很容易使用gets进入这些单独的组件 data ZState = ZState { int :: Int,str :: String } type Z a = StateT ZState IO a go :: Z () go = do i <- gets int s <- gets str replicateM i (liftIO $putStrLn s) 但这可能被认为是丑陋仍有两个原因:(1)放置和修改一般没有任何地方几乎一样好的故事和(2)我们不能轻易看到只影响的功能的类型,比如说,int状态并知道它不接触str.我们更喜欢保持这种类型保证的模块化. 如果你精通镜头,那就有一个名为 -- the real type is MUCH more general zoom :: Lens' mother child -> StateT child m a -> StateT mother m a 它将某个较大状态空间的子部分上的有状态计算“提升”到整个状态空间.或者,实际上,我们像这样使用它: data ZState = ZState { _int :: Int,_str :: String } makeLenses ''ZState type Z = StateT ZState IO a inc :: MonadState Int m => m () inc = modify (+1) yell :: MonadState String m => m () yell = modify (map toUpper) go :: Z () go = do zoom int $do inc inc inc zoom str yell i <- use int s <- use str replicateM i (liftIO $putStrLn s) 现在大多数问题都应该消失了 – 我们可以放大以隔离有状态操作,这些操作仅依赖于整个状态的子集,如inc和yell,并确定它们在类型中的隔离.我们还可以使用use来获取内部状态组件. 除此之外,缩放还可用于放大深埋在各种变压器堆栈内的状态.在这种情况下,完全通用类型可以正常工作 type Z a = EitherT String (ListT (StateT ZState IO)) a >>> :t zoom int :: EitherT String (ListT (StateT Int IO)) a -> Z a zoom int :: EitherT String (ListT (StateT Int IO)) a -> Z a 虽然这非常好,但完全通用的缩放需要一些繁重的技巧,你只能放大一些变压器层. (今天我很不清楚你如何将这个功能添加到你自己的图层,尽管可能是这样.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |