我正在寻找monads的创造性用途来学习.我已经读过某些地方,例如在AI中使用monad,但作为monad新手,我看不清楚如何.
请提供源代码和示例用法的链接.请不要标准单子.
Phil Wadler已经写过很多关于monad的论文,但是首先阅读的是很有趣的,任何程序员都可以访问它们.它被称为函数式编程的本质.本文包括源代码和示例用法.
我个人最喜欢的是概率monad ; 如果你能找到Sungwoo Park的博士论文,它有很多有趣的机器人示例代码.
还有LogicT(回溯monad变压器,具有公平操作和修剪).
它对AI搜索算法具有很好的价值,因为它具有公平分离的结构,例如,可以轻松地实现无限次成功的计算(交错).
它的用法在ICFP'05论文Backtracking,Interleaving和Terminating Monad Transformers中有所描述
你可以在博客A Neighborhood of Infinity找到有趣的高级单子.我可以注意到Vector Space Monad,以及它用于理性缠结的描述.不幸的是,我认为我不太了解这一点,在此解释它.
我最喜欢的单子之一是Martin Escardo的搜索单子.它可以在infinite-search
包装中的hackage上找到.
对于一组类型的元素,它是"搜索函数"的monad a
,即(a -> Bool) -> Maybe a
(在集合中查找与给定谓词匹配的元素).
monad的一个有趣用途是解析.Parsec是标准的例子.
阅读有关monad的系列文章,用于模拟概率和概率过程:http://www.randomhacks.net/articles/2007/03/03/smart-classification-with-haskell(关注prev/next parts的链接)
Harpy是一个用于运行时生成x86机器代码的软件包,它使用代码生成monad.从描述:
这是一个组合的读者状态异常monad,它处理处理代码缓冲区,发送二进制数据,重定位等的所有细节.
模块Harpy.X86CodeGen中的所有代码生成函数都存在于此monad中,并使用其错误报告功能以及monad维护的内部状态.
库用户可以通过monad传递用户环境和用户状态.此状态独立于内部状态,并且可由更高级别的代码生成库用于跨代码生成操作维护其自身状态.
我发现这是一个特别有趣的例子,因为我认为这种模式并不罕见:我自己发明了一些非常相似的东西,用于根据从(股票)市场数据源接收的消息为我的应用程序生成一组内部消息.事实证明,让一个框架跟踪各种"全局"事物同时组成简单的操作本身并不保持任何状态,这是一种非常舒适的方式.
我更进一步了解了一个用户状态(我称之为"子状态")的想法,它也可以通过monad传递:我有一个在monad运行期间切换和恢复状态的机制:
-- | Given a generator that uses different substate type, convert it -- to a generator that runs with our substate type. As well as the -- other-substate-type generator, the caller must provide an initial -- substate for that generator and a function taking the final substate -- of the generator and producing a new substate of our type. This -- preserves all other (non-substate) parts of the master state touched -- by the generator. -- mgConvertSubstate :: MsgGen msg st' a -> st' -> (st' -> st) -> MsgGen msg st a
这用于组合子的子组,这些组合子在短时间内需要它们自己的状态.这些只运行状态,不知道调用它的生成器的状态(这有助于使事情更加模块化),但这保留了任何非用户特定的状态,例如生成的当前消息列表和当前的一组警告或错误,以及控制流程(即允许总中止向上流动).
我想列出其他答案中尚未提及的几个monad.
该Omega
单子可以用来高效地遍历结果的无限列表.相比:
>>> take 10 $ liftM2 (,) [0..] [0..] [(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(0,9)] >>> take 10 $ runOmega $ liftM2 (,) (each' [0..]) (each' [0..]) [(0,0),(0,1),(1,0),(0,2),(1,1),(2,0),(0,3),(1,2),(2,1),(3,0)]
使用更高级的WeightedSearch
monad,还可以为计算分配权重,以便具有较低权重的计算结果首先出现在输出中.
有用的These
数据类型形成Monad
类似Either
但能够累积错误.该软件包还定义了MonadChronicle
类以及基于ChronicleT
monad变换器These
.