从序列中提取随机项

时间:2012-12-31 02:17:58

标签: haskell random sequence monads

我一直在尝试从序列中提取随机元素。我想要定义的函数如下:

getRandomInts :: Seq Int -> PureMT -> ((Seq Int, Int), PureMT)
getRandomInts ints gen = sampleState (fromJust $ choiceExtractSeq ints) gen

这是我得到的错误:

Overlapping instances for Data.Random.Lift.Lift
      transformers-0.3.0.0:Data.Functor.Identity.Identity
      (StateT PureMT transformers-0.3.0.0:Data.Functor.Identity.Identity)
  arising from a use of `sampleState'
Matching instances:
  instance [incoherent] (Monad m, MonadTrans t) =>
                        Data.Random.Lift.Lift m (t m)
    -- Defined in `Data.Random.Lift'
  instance [incoherent] Monad m =>
                        Data.Random.Lift.Lift
                          transformers-0.3.0.0:Data.Functor.Identity.Identity m
    -- Defined in `Data.Random.Lift'
In the expression:
  sampleState (fromJust $ choiceExtractSeq ints) gen
In an equation for `getRandomInt':
    getRandomInt ints gen
      = sampleState (fromJust $ choiceExtractSeq ints) gen

有没有人知道如何解决这个问题,或者,建议采用一种有效的方法从序列中获取随机元素(无需替换)?

1 个答案:

答案 0 :(得分:1)

我在这个程序中遇到了类似的问题:

sampleState (uniform (1 :: Int) 100 :: RVar Int) (mkStdGen 1)

这导致几乎相同的错误消息。这里的问题是Data.Random.Lift中存在重叠的实例,但没有最具体的实例,所以ghc拒绝该程序(在user's guide中描述)。

我解决这个问题的方法是提供一个比其他实例更具体的实例,所以简单地删除以下实例会让一切编译得很好(我已经包含了完整的语言编译指示和导入):

{-# LANGUAGE OverlappingInstances, 
             IncoherentInstances, 
             FlexibleInstances, 
             MultiParamTypeClasses #-}

import Data.Random
import Data.Random.Distribution.Uniform
import System.Random

import Data.Random.Lift
import Data.Functor.Identity
import Control.Monad.Trans.Class as T

main = print test

test :: (Int, StdGen)
test = sampleState (uniform (1 :: Int) 100 :: RVar Int) (mkStdGen 1)

instance MonadTrans t => Lift Identity (t Identity) where
  lift = T.lift

简而言之,尝试通过为Data.Random.Lift.Lift编写更具体的实例来指导编译器。

<强>更新

我已经为random-fu作者创建了一个pull request,其中有一个补丁,可以在库中修复它。在接受之前,您可以从我的fork开始,并使用cabal install为您完成这项工作。