ela*_*sca 8 haskell distribution
我想采用给定均值和标准差的正态分布进行采样.我知道如何在各种上下文中执行此操作,如Data.Random.Rvar或Data.Random.MonadRandom.但是,我的函数的上下文是Control.Monad.MonadRandom,我想保持这种方式,因为我的整个项目使用Control.Monad.MonadRandom.
有没有办法这样做,你能帮我这么做吗?
这是代码的样子.Pattern只是Data.Vector的别名Double和Weights是Data.Vector(Data.Vector Double)的别名(即矩阵)
train :: MonadRandom m => [Pattern] -> Int -> m Weights
train pats nr_hidden = do
ws_start <- ws_start''
foldM updateWS ws_start pats
where ws_start' = take p (repeat $ take nr_hidden $ repeat $ (normal 0.0 0.01))
ws_start'' = vector2D <$> (sequence $ map sequence ws_start')
p = length pats
Run Code Online (Sandbox Code Playgroud)
谢谢.
怎么用Data.Random.RVar里面的Control.Monad.MonadRandom?
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad.Random as CMR
import Data.Random as DR
import Data.Word (Word32)
gimmeRandom :: forall m . CMR.MonadRandom m => m Int
gimmeRandom = do
r <- runRVar (uniform 0 100) (getRandom :: m Word32)
return r
Run Code Online (Sandbox Code Playgroud)
实际上,您希望在具有类似语义的正式不同的 Monad中运行Monad .
Data.Random.MonadRandom并且Control.Monad.Random在形式上是不同的,因为它们是在不同的地方独立定义的,没有一个是另一个的实例(没有instance DR.MonadRandom m => CMR.MonadRandom m或其他方式).我们假设您在Control.Monad.Random界面中有一些代码:
import Control.Monad.Random as CMR
gimmeRandom :: CMR.MonadRandom m => m Int
gimmeRandom = do
r <- getRandomR (0, 100)
return r
Run Code Online (Sandbox Code Playgroud)
我们可以运行这个evalRand gimmeRandom StdGen,这给了我们一个Int.
现在代替getRandomR,您想要使用由提供的许多可用分发之一Data.Random.
对于此示例,我们将尝试替换getRandomR (0, 100)为uniform 0 100 :: RVar Int.如何我们得到Int了的是RVar Int在我们的CMR.MonadRandom环境?
我们想运行RVarmonad,我们可能必须提供一个随机数源,正如语义所暗示的那样.我们正在寻找像evalRand for CMR 这样的monad-escaping函数.这些转义函数有类型m a -> someStuffNeededToRunTheMonad -> a.
-- In a monad, using a RandomSource:
runRVar (uniform 1 100) DevRandom :: IO Int
Run Code Online (Sandbox Code Playgroud)
我们来看看runRVar:
runRVar :: RandomSource m s => RVar a -> s -> m a
Run Code Online (Sandbox Code Playgroud)
是的,这是一种转义函数:给定一个RVar随机数的源和它,它返回我们RVar自己的monad内部的随机结果m.然而,这要求有一个instance RandomSource m s说明s是我们monad的随机源m.我们来看看那个例子.
我们的monad是什么m?我们想要运行RVarin gimmeRandom,所以monad是CMR.MonadRandom m => m(所有monad都实现CMR.MonadRandom).什么是随机源s?不知道了.让我们看看RandomSource存在哪些实例的文档:
RandomSource IO DevRandom
...
Monad m0 => RandomSource m0 (m0 Word32)
Monad m0 => RandomSource m0 (m0 Word64)
...
Run Code Online (Sandbox Code Playgroud)
啊哈!这就是说任何单子m0是一个实例RandomSource连同值从这个单子来(例如m0 Word32).这当然也适用于我们的monad CMR.MonadRandom.我们也可以看到s,m0 Word32必须由随机性源生成的随机值.
我们应该通过在作为s中runRVar (uniform 0 100) s?在我们的 monad 中产生随机数的东西,类型CMR.MonadRandom m => m Word32.CMR生成任意事物的功能是什么,例如一些Word32?getRandom.基本上我们想写:
gimmeRandom :: CMR.MonadRandom m => m Int
gimmeRandom = do
r <- runRVar (uniform 0 100) getRandom
return r
Run Code Online (Sandbox Code Playgroud)
嗯,那不编译:
Could not deduce (RandomSource m (m0 a0))
arising from a use of `runRVar'
from the context (CMR.MonadRandom m)
bound by the type signature for
gimmeRandom :: CMR.MonadRandom m => m Int
Run Code Online (Sandbox Code Playgroud)
RandomSource m (m0 a0)?这是奇怪的m和m0似乎被确认为不同的编译器的单子; 我们希望它们是一样的,就像在RandomSource m0 (m0 Word64).
让我们把完整的签名放到那个地方:
r <- runRVar (uniform 0 100) (getRandom :: CMR.MonadRandom m => m Word32)
Run Code Online (Sandbox Code Playgroud)
还是一样的错误.这是因为m在该类型签名中,实际上是任何 monad实现CMR.MonadRandom,不一定是MonadRandom我们的gimmeRandom类型签名.
(这与阴影中的阴影概念相同,(\x -> (\x -> f x))其中内部\x是用于的f x;或者在一阶逻辑中?x . F(x) ? ?x . G(x),其中xin G(x)是最内部定义的一个并且不需要相同,甚至不是相同的类型,作为外部的那个?x;或者实际上在内部作用域中具有变量隐藏/阴影的任何其他编程语言 - 只是在这里它是类型变量阴影).
因此,我们唯一需要做的就是告诉编译器在getRandom调用中,我们不希望它适用于任何类型MonadRandom,但正是MonadRandom m我们在gimmeRandom类型签名中所拥有的.
我们可以使用ScopedTypeVariables扩展来做到这一点:
{-# LANGUAGE ScopedTypeVariables #-}
[...]
gimmeRandom :: forall m . CMR.MonadRandom m => m Int
gimmeRandom = do
r <- runRVar (uniform 0 100) (getRandom :: m Word32)
return r
Run Code Online (Sandbox Code Playgroud)
这使得从顶级类型签名中精确选择min .getRandom :: m ... CMR.MonadRandom m
这确实编译了,问题解决了:我们可以使用接口Data.Random在代码中使用发行版MonadRandom.我们可以轻松地替换uniform另一个分发.
总而言之,我们有
runRVar)runRVar (uniform 0 100) getRandom)getRandom应该使用来编译它.如果你想知道为什么我们Word32从我们可以选择的实例中任意选择,我们只需要以某种形式给出随机源,而Word32是Data.Random生成其他随机内容的输入之一.