我想从monad变换器堆栈中的列表中获取加权样本。
我设法让这个最小的例子进行了类型检查,但我不理解运行main
时出现的错误信息,我不知道怎么做解决它。
{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts #-}
module Testing where
import Control.Monad.IO.Class (liftIO, MonadIO)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.State.Lazy (modify, runStateT, StateT)
import Control.Monad.Trans.Reader (ask, runReaderT, ReaderT)
import Data.Random
import Data.Random.Distribution.Uniform.Exclusive (Excludable)
import Data.Random.Shuffle.Weighted (weightedSample)
testS :: [(Int, Int)]
testS = [(1,c) | c <- [11..20]]
loop :: (Num w, Ord w, Show a, MonadIO m, Excludable w, Distribution Uniform w, MonadRandom (StateT [[a]] m)) => ReaderT [(w, a)] (StateT [[a]] m) ()
loop = do
s <- ask
a <- lift $ sample $ weightedSample 1 s
liftIO $ print a
lift $ modify ((:) a)
main :: (MonadIO m, MonadRandom (StateT [[Int]] m)) => m ((), [[Int]])
main = runStateT (runReaderT loop testS) []
实际程序应该通过从初始配置(testS
)中选择一个随机问题来帮助学习,然后更新状态中的权重,以便用户出错的问题变得更有可能。
以下是在ghci中运行main
时出现的错误:
No instance for (random-source-0.3.0.6:Data.Random.Internal.Source.MonadRandom
(Control.Monad.Trans.State.Lazy.StateT [[Int]] m0))
arising from a use of `main'
Possible fix:
add an instance declaration for
(random-source-0.3.0.6:Data.Random.Internal.Source.MonadRandom
(Control.Monad.Trans.State.Lazy.StateT [[Int]] m0))
In the expression: main
In an equation for `it': it = main
答案 0 :(得分:2)
我似乎无法安装random-fu
进行测试,但根据浏览文档,我仍然猜测可能是正确的。
该行
a <- lift $ sample $ weightedSample 1 s
尝试在基础monad中运行sample $ weightedSample 1 s
StateT [[Int]] IO
但是,当StateT
monad的状态是受支持的随机数生成器状态之一时,MonadRandom
monad仅为IO
。
您可能希望在MonadRandom
中运行它,lift
本身就是StateT [[Int]] IO
。
换句话说,添加另一个{{1}}。
顺便说一句,如果这是正确的,那么它最初仍然可以检测到的理由是, 理论上可以为{{1}}添加一个实例。 (但你可能没有。)