如何在计算随机值的 haskell 程序中构造 monad?

how to structure monads in haskell programs which compute on random values?

我有一个几乎是纯数学计算的程序。问题是其中一些计算对 monte carlo 生成的值进行操作。

看来我有两种设计选择:

我所有的计算函数都采用包含预生成的 monte carlo 链的附加参数。这让我可以在任何地方保留纯函数,但由于存在调用其他函数的函数,这会在代码库中增加很多行噪音。

另一种选择是使所有计算函数成为一元函数。这似乎很不幸,因为一些函数甚至没有使用那些随机值,它们只是调用一个函数,而这个函数又调用一个需要随机值的函数。

这里有关于首选设计的指导吗?具体来说,代码中涉及 ​​monte carlo 值的单子函数/非单子函数的分离?

tl;博士: 考虑抽象随机函数生成器并将其作为参数传递。 Haskells 类型 类 应该可以帮助您尽可能地隐藏该抽象。

不幸的是,这里没有灵丹妙药。由于您正在使用副作用,因此您的 "functions" 根本不是正确意义上的功能。 Haskell 不允许您隐藏该事实(这是其安全保证的最大部分)。因此,您需要以某种方式表达这一事实。您似乎还混淆了单子操作和(普通)函数之间的区别:(间接)使用随机值的函数隐式是单子的。非单子函数总是可以在单子操作中使用。因此,您可能应该实现所有真正的非单子函数,然后看看它能走多远。

作为一个完全不相关的旁注:如果懒惰不是必需的并且 Haskell 强大的安全性对您来说是一个负担,但您仍然想编写(大部分)功能代码,您可以试试 OCaml(或任何其他 ML 方言)。

The other option is to make all the computation functions monadic. This seems unfortunate since some of the functions aren't even using those random values they're just calling a function which calls a function which needs the random values.

我建议采用这种方法,我不同意你的评估,即 "unfortunate." monad 擅长的是 准确地说 将你的纯代码与你的副作用分开代码。你的纯函数只能有纯类型,Functor/Applicative/Monad 方法用于随机生成部分的 "hook them up"。思考标准操作的签名(这里专门针对一些理想化的 Random monad 类型):

-- Apply a pure function to a randomly selected value.
fmap :: (a -> b) -> Random a -> Random b

-- Apply a randomly selected function to a randomly selected argument.
-- The two random choices are independent.
(<*>) :: Random (a -> b) -> Random a -> Random b

-- Apply a two-argument function to a randomly selected arguments.
-- The two random choices are independent.
liftA2 :: (a -> b -> c) -> Random a -> Random b -> Random c

-- Make a `Random b` choice whose distribution depends on the value
-- sampled from the `Random a`.
(>>=) :: Random a -> (a -> Random b) -> Random b

所以你的方法的重新制定版本是:

  • 尽可能编写纯函数。
  • 使用 Functor/Applicative/Monad class 操作使这些纯函数适应随机值。
  • 无论您在何处发现多余地提及 Random 类型的函数,找出如何使用那些 classes 的操作(或丰富的实用函数)来分解 Random 部分为他们而存在)。

顺便说一句,这不是特定于随机数生成,而是适用于 any monad。

您可能会喜欢阅读这篇文章,并且可能想查看作者的随机生成 monad 库:

我怀疑您是否需要遵循本文中使用自由 monad 进行建模的方法,但关于概率分布 monad 的概念性知识可能会有所帮助。