Haskell 从列表中提取一个随机元素(并将其删除),学习单子
我通过Haskell维基和我自己的新手实验在Haskell学习单子 作为我的第一步,我已经使用great library(由Daniel Díaz编写)将书中与monads相关的部分复制粘贴到我自己的PDF中,同时轻松阅读这些硬文本(因为其内容而硬) 下面是我第一次尝试实践我学到的东西:一个函数的7个版本,它获取一个列表并从该列表中返回一个随机元素 现在我的主要问题是,我应该在“移除元素”部分使用monad变压器吗?我听说他们是用来混合单子的, 我知道我将使用State单子和List单子 除此之外,对我的代码的任何评论都将不胜感激(风格的评论最多,因为monad是关于用风格写作的?:p)Haskell 从列表中提取一个随机元素(并将其删除),学习单子,haskell,random,monad-transformers,state-monad,Haskell,Random,Monad Transformers,State Monad,我通过Haskell维基和我自己的新手实验在Haskell学习单子 作为我的第一步,我已经使用great library(由Daniel Díaz编写)将书中与monads相关的部分复制粘贴到我自己的PDF中,同时轻松阅读这些硬文本(因为其内容而硬) 下面是我第一次尝试实践我学到的东西:一个函数的7个版本,它获取一个列表并从该列表中返回一个随机元素 现在我的主要问题是,我应该在“移除元素”部分使用monad变压器吗?我听说他们是用来混合单子的, 我知道我将使用State单子和List单子 除此之
------------------------去随机性------------------------
------------------------去随机性------------------------
------------------------TERCER打算消除随机性-------------------------
------------------------CUARTO打算消除随机性-------------------------
------------------------昆托意图去随机性-------------------------
------------------------性倾向于去随机性--------------------------
extractor\::[a]->状态StdGen a
提取器_xs=
做
发电机(st,st)
设n=长度xs
设(k,newGen)=randomR(0,n-1)发生器
放纽根
返回(xs!!k)
--德尔科迪戈贸易公司:
提取器_uxS=
获取>>=
\生成器->让n=长度xs英寸
(设(k,newGen)=随机r(0,n-1)发生器
(放入newGen>>返回(xs!!k)))
--*Main>:t提取器“
--提取器“::(随机生成t,单子m)=>[b]->StateT m b
--*Main>:t提取器_
--提取器::[a]->状态StdGen a
--=======o o======
-- ___________
-- |___________| -------------------------------------------------------------------------------
--\\/\/\\\\\\\-------------------------------------最终版本------------------------
-- |_\/__\/__| -------------------------------------------------------------------------------
-- |___________|
-- ??????????????????? (不知道该选哪一个)
顺便说一句,我这样做是为了完成我的数学学位,之后我将通过Haskell:D(我是在要求a吗?)
我应该为“移除元素”部分使用monad变压器吗?我已经读到它们被用来混合单子,我知道我将使用状态单子和列表单子
但是你没有使用单子列表!您只是在使用列表。如果说您正在使用列表monad,则意味着您正在使用列表专用的(>>=)
或返回
(或类似的monad
-列表专用的多态函数),而您没有这样做。因此,我认为使用状态
,而不使用任何变压器是非常有意义的
除此之外,对我的代码的任何评论都将不胜感激(风格的评论最多,因为monad是关于用风格写作的?:p)
我最喜欢你的第四次尝试,提醒你的是:
extractR'''' :: [a] -> State StdGen a
extractR'''' xs = pr1 >>= f
where
n = length xs
pr1 = state $ randomR (0,n-1)
f = \k -> state ( \s -> (xs !! k , s) )
我唯一要做的调整是我发现你的f
有点太复杂了。由于您根本没有修改状态,因此不需要使用特定于状态的函数;可以写
f = \k -> return (xs !! k)
相反。然后我们可以应用单子定律,即:
m >>= (\x -> return (f x)) = fmap f m
因此,我希望看到的最终实施是:
extractR :: [a] -> State StdGen a
extractR xs = fmap (xs!!) pr1
where
n = length xs
pr1 = state $ randomR (0,n-1)
(当然,人们可以用几种其他方式拼写fmap
,在这种情况下,它们主要在美学上有所不同,比如()
,liftA
,或liftM
),您可能想看看MonadRandom
包
import Control.Monad.Random
extractR :: MonadRandom m => [a] -> m a
extractR xs = (xs !!) <$> getRandomR (0, length xs - 1)
import Control.Monad.Random
提取器::MonadRandom=>[a]->MA
提取器xs=(xs!!)getRandomR(0,长度xs-1)
MonadRandom
约束由IO
和RandT g m
满足,它本质上是一个基于StateT StdGen
的monad,在纯代码中可用
此外,该库定义了uniform
,它相当于您的extractor
(尽管它的实现相当复杂)。除第一个版本外,其他所有版本都是合理的(其中一个版本是PRNG的误用,与Haskell或Monads无关),“应该”做的是对解决您的特定问题最有用的事情,没有唯一的办法。
extractR_ :: [a] -> State StdGen a
extractR_ xs = pr1 >>= f
where
n = length xs
pr1 = state $ randomR (0,n-1)
f = \k -> state ( \s -> (xs !! k , g s) )
g = \stdG -> snd $ next stdG
-- monadic code, se actualiza 2 veces el StdGen
extractR_' :: [a] -> State StdGen a
extractR_' xs =
do
generator <- get -- get = state $ \st -> (st,st)
let n = length xs
let (k, newGen) = randomR (0,n-1) generator
put newGen
return (xs!!k)
-- traduccion del codigo:
extractR_'' xs =
get >>=
\generator -> let n=length xs in
( let (k, newGen)=randomR (0,n-1) generator in
(put newGen >> return (xs!!k) ) )
-- *Main> :t extractR_''
-- extractR_'' :: (RandomGen t, Monad m) => [b] -> StateT t m b
-- *Main> :t extractR_
-- extractR_ :: [a] -> State StdGen a
-- ======o o======
-- ___________
-- |___________| -------------------------------------------------------------------------------
-- |\ /\ /\| ------------------------ VERSION FINAL ------------------------
-- |_\/__\/__| -------------------------------------------------------------------------------
-- |___________|
-- ??????????????????? (dont know which to choose)
extractR'''' :: [a] -> State StdGen a
extractR'''' xs = pr1 >>= f
where
n = length xs
pr1 = state $ randomR (0,n-1)
f = \k -> state ( \s -> (xs !! k , s) )
f = \k -> return (xs !! k)
m >>= (\x -> return (f x)) = fmap f m
extractR :: [a] -> State StdGen a
extractR xs = fmap (xs!!) pr1
where
n = length xs
pr1 = state $ randomR (0,n-1)
import Control.Monad.Random
extractR :: MonadRandom m => [a] -> m a
extractR xs = (xs !!) <$> getRandomR (0, length xs - 1)