Haskell 改进代码以生成发行版

Haskell 改进代码以生成发行版,haskell,statistics,Haskell,Statistics,我是Haskell的新手,我想知道如何/如果我能使这段代码更加高效和整洁。它看起来不必要的长和不整洁 我的脚本生成了一个列表,其中列出了10次抛硬币的平均值 import Data.List import System.Random type Rand a = StdGen -> Maybe (a,StdGen) output = do gen <- newStdGen return $ distBernoulli 10 10 gen distBernoulli

我是Haskell的新手,我想知道如何/如果我能使这段代码更加高效和整洁。它看起来不必要的长和不整洁

我的脚本生成了一个列表,其中列出了10次抛硬币的平均值

import Data.List
import System.Random

type Rand a = StdGen -> Maybe (a,StdGen)

output = do
    gen <- newStdGen
    return $ distBernoulli 10 10 gen

distBernoulli :: Int -> Int -> StdGen -> [Double]
distBernoulli m n gen = [fromIntegral (sum x) / fromIntegral (length x) | x <- lst]
    where lst = splitList (randomList (n*m) gen) n

splitList :: [Int] -> Int -> [[Int]]
splitList [] n = []
splitList lst n = take n lst : splitList (drop n lst) n

randomList :: Int -> StdGen -> [Int]
randomList n = take n . unfoldr trialBernoulli

trialBernoulli :: Rand Int
trialBernoulli gen = Just ((2*x)-1,y)
                 where (x,y) = randomR (0,1) gen
导入数据。列表
导入系统。随机
输入Rand a=StdGen->Maybe(a,StdGen)
输出=do
gen Int->StdGen->[双精度]
distBernoulli m n gen=[from积分(和x)/from积分(长度x)| x Int->[[Int]]
拆分列表[]n=[]
拆分列表lst n=取n lst:拆分列表(放置n lst)n
随机列表::Int->StdGen->[Int]
随机列表n=取n.展开器trialBernoulli
trialBernoulli::Rand Int
trialBernoulli-gen=Just((2*x)-1,y)
式中(x,y)=randomR(0,1)gen

非常感谢您的帮助。

我不确定是否理解您的代码或您的问题

但在我看来,你所需要做的就是生成一个随机的1和0的列表,然后用
map
将它们除以它们的长度,然后用
foldl
将它们相加

比如:

makeList n lis=如果n/=0,则 生成列表(n-1)随机(0,1):lis 其他的 利斯


然后让它应用一个Map和Foldl或Foldr。

编辑:我发布这个太快了,与行为不匹配,现在应该很好了

import Control.Monad.Random
import Control.Monad (liftM, replicateM)
知识:如果你喜欢随机化,那么就用它吧

样式:仅导入您使用的符号有助于可读性,有时还有助于可维护性

output :: IO [Double]
output = liftM (map dist) getLists
注意:我给了输出一个显式类型,但我知道它不一定是IO

风格:

1) 将IO与纯函数分开通常是很好的。在这里,我将随机列表的获取从分布计算中分离出来。在你的例子中,它是纯的,但是你通过生成器将“随机”列表与分布函数结合起来;我将把这些部分分开

2)阅读。考虑使用<代码> > = <代码>代替

output = do
   gen <- new
   return $ dist gen

任何以
M
结尾的知识都与原始知识类似,但对于单子而言。在这种情况下,如果您使用了Data.List
replicate
函数,则应该熟悉
replicate

getList :: MonadRandom m => Int -> m [Int]
getList m = liftM (map (subtract 1 . (*2)) . take m) (getRandomRs (0,1::Int))

风格:如果我经常做某件事,我希望在它自己的函数中有一个实例(getList)然后在一个单独的函数中进行重复。

我将以一种稍微不同的方式解决这个问题。首先,我将定义一个函数,该函数将从伯努利分布中以成功概率对翻转进行无限采样。
p

getList :: MonadRandom m => Int -> m [Int]
getList m = liftM (map (subtract 1 . (*2)) . take m) (getRandomRs (0,1::Int))
flips :: Double -> StdGen -> [Bool]
flips p = map (< p) . randoms
我认为这符合你对伯努利的定义:

*Main> distBernoulli 10 10 $ mkStdGen 0
[-0.2,0.4,0.4,0.0,0.0,0.2,0.0,0.6,0.2,0.0]
(请注意,我使用的是handy软件包中的
splitEvery
,因此您必须安装该软件包并将
import Data.List.Split(splitEvery)
添加到导入中。)


这种方法更一般,我认为更简洁,但真正的主要区别在于我使用的是
randoms
splitEvery
使用上面的方法,我现在使用这个

import Data.List
import System.Random

type Rand a = [a]

distBernoulli :: Int -> Int -> StdGen -> [Double]
distBernoulli m n gen = [fromIntegral (sum x) / fromIntegral (length x) | x <- lst]
    where lst = take m $ splitList (listBernoulli gen) n

listBernoulli :: StdGen -> Rand Int
listBernoulli = map (\x -> (x*2)-1) . randomRs (0,1)

splitList :: [Int] -> Int -> [[Int]]
splitList lst n = take n lst : splitList (drop n lst) n
导入数据。列表
导入系统。随机
键入Rand a=[a]
distBernoulli::Int->Int->StdGen->[双精度]
distBernoulli m n gen=[from积分(和x)/from积分(长度x)| x Rand Int
listBernoulli=map(\x->(x*2)-1).randomRs(0,1)
拆分列表::[Int]->Int->[[Int]]
拆分列表lst n=取n lst:拆分列表(放置n lst)n

感谢您的帮助,我欢迎您的进一步评论:)

对不起,我解释得不好。我基本上是在尝试创建数据以建立标准正态分布。通过虚拟掷硬币(结果为1或-1)10次,取结果的平均值,我们得到-0.2。通过这个过程,比如说1000次,我们可以绘制结果及其频率,并获得正态分布。我试图创建一个双倍列表,我可以绘制这个分布。为了澄清,这个脚本的结果可能是[0.2,0.0,0.0,-0.4,0.6,0.0,-0.2,0.2,0.4,0.0]
*Main> distBernoulli 10 10 $ mkStdGen 0
[-0.2,0.4,0.4,0.0,0.0,0.2,0.0,0.6,0.2,0.0]
import Data.List
import System.Random

type Rand a = [a]

distBernoulli :: Int -> Int -> StdGen -> [Double]
distBernoulli m n gen = [fromIntegral (sum x) / fromIntegral (length x) | x <- lst]
    where lst = take m $ splitList (listBernoulli gen) n

listBernoulli :: StdGen -> Rand Int
listBernoulli = map (\x -> (x*2)-1) . randomRs (0,1)

splitList :: [Int] -> Int -> [[Int]]
splitList lst n = take n lst : splitList (drop n lst) n