haskell - 在 monad 变压器堆栈中使用 WeightedSample 时为 "No instance for MonadRandom"

标签 haskell monads monad-transformers

我想从 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  

最佳答案

我似乎无法安装 random-fu 进行测试,但根据浏览文档,我仍然猜测这可能是正确的。

线路

a <- lift $ sample $ weightedSample 1 s

尝试在底层 monad 中运行 sample $weightedSample 1 s

StateT [[Int]] IO

但是,当 StateT monad 的状态是受支持的随机数生成器状态之一时,它们只是 MonadRandom

您可能想在 IO 中运行它,它本身就是一个 MonadRandom

换句话说,添加另一个提升

顺便说一句,如果这是正确的,它最初仍然进行类型检查的原因是,如果您愿意,理论上您可以为 StateT [[Int]] IO 添加一个实例。 (但你可能不知道。)

关于haskell - 在 monad 变压器堆栈中使用 WeightedSample 时为 "No instance for MonadRandom",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26069630/

相关文章:

error-handling - 使用单子(monad)批量进行失败的转换?

scala - 状态 monad - 调整仅适用于部分状态的功能?

haskell - 将嵌套类型转换为 monad 转换器堆栈

haskell - 如果条件为真,则合并多个列表

windows - 我可以从 Windows 上的 ghc Haskell 进程转储中收集哪些信息?

compiler-construction - 编译成惯用的 C

haskell - 生成所有可能的树

haskell - 哪种代数模式适合这种类型的树?

haskell - 组合两个单子(monad)变压器堆栈时无法派生 Applicative

haskell - 如何将两个 ErrorT monad 转换器堆叠在一起?