gpt4 book ai didi

haskell - 有没有一种明智的方法来解压缩状态单子(monad)?

转载 作者:行者123 更新时间:2023-12-04 14:34:57 24 4
gpt4 key购买 nike

我想要一个像这样的功能:

unzipState :: (MonadState s m) => m (a, b) -> (m a, m b)

这将需要一个返回元组的(有状态的)计算,并将返回两个(相关的)计算。

当然,困难在于从一个或另一个计算中提取值应该更新另一个计算中的状态。

一个有用(和激励)的应用程序是 Random monad,表示为
{-# LANGUAGE Rank2types #-}
import qualified System.Random as SR
import Control.Monad.State

type Random a = forall r. (State RandomGen r) => State r a

假设你有:
normal :: Random Double
-- implementation skipped

correlateWith :: Double -> Random (Double, Double) -> Random (Double, Double)
correlateWith rho w = do
(u, v) <- w
return $ (u, p * u + (1 - p * p) * v)

能够这样写是很自然的:
let x = normal
y = normal
(u, v) = unzipState $ correlateWith 0.5 $ liftM2 (,) x y
... now I am able to perform computation on u and v as correlated random variables

有没有明智的方法来做到这一点?我挣扎了一下,但没有设法得到任何东西。胡格尔也无济于事。

编辑

很好的答案向我表明我的问题定义不明确。不过,有人可以解释一下为什么 python 中的以下实现(我认为是正确的,但没有经过太多测试)不能在 Haskell 中翻译(具有 STrefs、闭包和其他我承认我不掌握的东西的魔力; -)):
def unzipState(p):
flist, glist = [], []
def f(state):
if not flist:
(fvalue, gvalue), newstate = p(state)
glist.insert(0, gvalue)
return (fvalue, newstate)
else:
fvalue = flist.pop()
return (fvalue, state)
def g(state):
if not glist:
(fvalue, gvalue), newstate = p(state)
flist.insert(0, fvalue)
return (fvalue, newstate)
else:
gvalue = glist.pop()
return (gvalue, state)
return (f, g)

并不是说有状态代码可以在 Haskell 中翻译,但我觉得理解为什么以及何时(即使是在一个例子中)它不能完成会大大提高我的理解。

编辑2

现在很清楚了。函数 f 和 g 显然不是纯函数,因为它们的输出不仅取决于 state 的值。

再次感谢 !

最佳答案

无法构造通用函数unzipState这可以满足您的需求,只是因为您可能无法为其预期效果提供正式规范。换句话说,假设你已经实现了一些函数 unzipState .你怎么知道它是正确的?您必须证明它满足某些定律/方程,但这里的麻烦是首先要找到这些定律。

虽然我想我明白你想做什么,Random monad 也清楚地说明了为什么它不能完成。要看到这一点,你必须放弃具体的实现 type Random a = ...并考虑由

v :: Random a means that v is a probability distribution of values of type a



“绑定(bind)”操作 (>>=) :: Random a -> (a -> Random b) -> Random b只是一种从旧概率分布构造新概率分布的方法。

现在,这意味着 unzipState简单地返回一对概率分布,可以用来构造其他概率分布。关键是,虽然 do语法看起来很有启发性,但你 不实际采样 随机变量,您只需计算概率分布。随机变量可以相关,但概率分布不能。

请注意,可以创建不同的 monad RandomVariable a对应于随机变量。但是,您必须提前固定样本空间 Ω。实现是
type RandomVariable a = Ω -> a



如果你想要随机变量和自动扩大样本空间的能力,你可能需要两个绑定(bind)操作
bind1 :: Random Ω a -> (a -> Random Ω b) -> Random Ω b
bind2 :: Random Ω1 a -> (a -> Random Ω2 b) -> Random (Ω1,Ω2) b

和一些依赖类型的魔法来处理像 (Ω1,(Ω2,Ω3)) 这样的产品的扩散。 .

关于haskell - 有没有一种明智的方法来解压缩状态单子(monad)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4634807/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com