2012-12-31 87 views
1

我一直試圖從序列中提取一個隨機元素。我試圖定義功能如下:從序列中提取隨機項目

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

我也有類似的問題,這個程序:

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來指導編譯器。

更新

我創建了一個pull request到隨機福作者通過在圖書館修復了這個補丁。在此之前,您可以從我的fork中拉出,並使用cabal install爲您工作。

+0

另一種方法是通過用'(runState.ampleRVar)'替換'sampleState'來避免'Lift'(我喜歡完全停止使用它,它總是會導致這樣的問題)。後一個函數在'Data.RVar'模塊中,它稍低一些,並且不使用'Lift'。 – mokus