monads的创意用途

我正在寻找monads的创意用途来学习。 我读过某个地方,人工智能中使用monad,但作为monad新手,我看不出如何。

请包括一个链接到源代码和样本用法。 没有标准的单子,请。

Phil Wadler写了很多关于Monad的文章 ,但是首先阅读的文章非常有趣,任何程序员都可以访问。 它被称为函数式编程的本质 。 本文包括源代码和样本用法。

我个人最喜欢的是monad概率 , 如果你能findSungwoo Park的博士论文,那么它有很多来自机器人的有趣的示例代码。

也有LogicT (回溯单体变压器公平的操作和修剪)。

它对于AIsearchalgorithm具有很好的价值,因为它具有公平的分离结构,例如,可以轻松实现成功无限次数的计算( 交错 )。

它的用法在ICFP'05论文的Backtracking,Interleaving和Terminating Monad Transformers中有描述

你可以在博客无穷的邻里find有趣和先进的单子。 我可以注意到Vector Space Monad ,以及它用于合理缠结的描述。 不幸的是,我不认为我明白这一点足以在此解释。

我最喜欢的单子之一是马丁埃斯卡多的search单子 。 它可以在infinite-search包中的hackage上find。

它是一组types为a的元素的“search函数”的单子,即(a -> Bool) -> Maybe a (find匹配给定谓词的集合中的元素)。

阅读关于单子的系列文章,用于模拟概率和概率过程: http : //www.randomhacks.net/articles/2007/03/03/smart-classification-with-haskell (链接到上一个/下一个部分)

Harpy是x86机器代码的运行时生成包,使用代码生成monad 。 从描述:

这是一个组合的读写器状态exceptionmonad,它处理所有处理代码缓冲区,发送二进制数据,重定位等的细节。

模块Harpy.X86CodeGen中的所有代码生成函数都存在于这个monad中,并使用它的错误报告function以及由monad维护的​​内部状态。

库用户可以通过monad传递用户环境和用户状态。 这个状态独立于内部状态,可以被更高级别的代码生成库用来在代码生成操作中维护自己的状态。

我发现这是一个特别有趣的例子,因为我认为这种模式并不罕见:我发明了一些非常相似的东西,根据从(股票)市场数据馈送收到的消息为我的应用程序生成一组内部消息。 事实certificate,这是一个非常舒适的方式,让一个框架跟踪各种“全局”的事物,同时组成简单的操作,本身没有任何状态。

我进一步提出了一个有关用户状态(我称之为“子状态”)的想法,这个状态也可以通过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 

这用于短期内需要自己状态的组合子组。 这些运行只是他们的状态,不知道任何关于调用它的生成器的状态(这有助于使事物更模块化),但是这保留了任何非用户特定的状态,例如生成的消息的当前列表和当前的一组警告或错误,以及控制stream程(即允许总的中止向上stream动)。

monad的一个有趣用途是parsing。 Parsec是标准的例子。

我想列举其他答案中尚未提及的几个单子。

枚举和加权search单子

Omega monad可以用来有效地遍历无限的结果列表。 比较:

 >>> 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 ,也可以为计算分配权重,以便权重较低的计算结果在输出中首先出现。

积累错误monad

一个有用的These数据types形成一个Monad类似于Either ,但能够积累错误。 该包还定义了MonadChronicle类以及基于These ChronicleT monad变换器 。