我有一个几乎是纯数学计算的程序。问题是其中一些计算对蒙特卡罗生成的值进行操作。
看来我有两个设计选项:
我的所有计算函数都采用附加参数,其中包含预先生成的蒙特卡罗链。这让我可以在任何地方保留纯函数,但由于有些函数调用其他函数,这会给代码库增加很多线路噪音。
另一种选择是使所有计算函数成为一元函数。这似乎很不幸,因为某些函数甚至没有使用这些随机值,它们只是调用一个函数,该函数调用一个需要随机值的函数。
这里有关于首选设计的任何指导吗?具体来说,涉及蒙特卡罗值的代码中一元函数/非一元函数的分离?
最佳答案
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.
我建议遵循这种方法,并且我不同意您认为这是“不幸的”的评估。 monad 所擅长的准确是将纯代码与副作用代码分开。您的纯函数可以只具有纯类型,并且 Functor
/Applicative
/Monad
方法用于将它们与随机生成部分“ Hook ” 。思考标准操作的签名(这里专门针对一些理想化的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
类操作调整这些纯函数以处理随机值。 - 无论您在何处发现多余地提及
Random
类型的函数,请弄清楚如何使用这些类的操作(或使用这些类的操作)将Random
部分分解出来对他们而言存在)。
顺便说一句,这并不特定于随机数生成,而是适用于任何 monad。
您可能喜欢阅读这篇文章,并且可能想查看作者的随机生成 monad 库:
我怀疑您是否需要遵循本文使用免费 monad 进行建模的方法,但有关概率分布 monad 的概念部分可能会有所帮助。
关于haskell - 如何在计算随机值的 haskell 程序中构造 monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37195146/