2010-11-28 1 views
0

그래서 저는 roguelike를 작성 중이며 무작위로 던전을 생성해야합니다. system.random을 사용할 수는 있지만 정말로 순수하게 만들고 싶습니다. newPureMT를 사용하여 메르 센 트위스터 무작위 소스를 생성 한 다음 stateT 및 readerT와 같은 몇 가지 모나드 변압기와 몇 가지 다른 버전으로 전달하려고합니다. 내가의 라인을 따라 뭔가 끝낼 것이다 그래야 :random-fu 패키지를 사용하여 모나드에서 puremt을 수행하는 방법

genDungeon = do 
    x <- getRandomNumbers 
    genrooms x 
    y <- getRandomNumbers 
    gendoors x 
    etc 

나는 IO 모나드에 체류하지 않고이 작업을 수행하는 방법을 알아낼 수 없습니다.

sample (uniform 1 100) :: State PureMT Int 

내가 할 수 있어야 의미 :

Overlapping instances for Data.Random.Lift.Lift 
          Data.Functor.Identity.Identity 
          (StateT PureMT Data.Functor.Identity.Identity) 
    arising from a use of `sample' at <interactive>:1:0-28 
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 Data.Functor.Identity.Identity m 
    -- Defined in Data.Random.Lift 

내가 가지고있는 오류를 ghci로를 산출 입력도

blah = do 
    x <- newPureMT 
    runState genDungeon x 

그러나 예를 들어,이 예제를 제공합니다 그게 무슨 뜻인지, 어떻게 고쳐야할지 전혀 모르겠다.

나는 이것을 알아 내려고 며칠을 보냈는데, 나는 완전히 단서가 없다. 어떤 꽤 무거운 타입의 시그니처가 있고 물건을 얻기 위해 적용해야하는 물건을 들어 올리는 것은 꽤 분명합니다. 그러나 나는 그들이 무엇인지 또는 어떻게해야 하는지를 알 수 없습니다.

편집 : 좋아, 그래서 메르 센 트위스터 코드를보고 있었고 PureMT가 system.random으로 전달할 수있는 randomgen의 인스턴스이며 PureMT가 순수한 코드를 가져 와서 random-fu 불필요한. 나는이 코드가 random-fu로 작동하도록하는 방법을 이해할 수 있었으면 좋겠다. 다른 무작위 배포판처럼 많은 여분의 능력을 제공하지만 그의 계획은 내 프로젝트에서 할 것이다.

편집 : 좋아, 그럼이 코드와 함께 종료 : 거의이 날 내가 구문 원하는 것을 수행 할 수 있습니다

rand :: (RandomGen g, MonadState g m) => Int -> Int -> m Int 
rand lo hi = do 
    r <- get 
    let (val, r') = randomR (lo, hi) r 
    put r' 
    return val 


gendungeons = replicateM 10 $ do 
    x <- rand 0 24 
    y <- rand 4 10 
    z <- replicateM 10 $ rand 5 50 
    let dungeon = makeadungeonpurelywiththeserandomvalues x y z 
    return dungeon 


test = do 
    x <- newPureMT 
    let dungeons = runState gendungeons x 
    return dungeons 

하고 빠르게 많아서해야한다 그래서 메르 센 트위스터를 사용 . 저를 괴롭히는 유일한 이유는 모든 단일 세대 세대에서 국가 모나드의 종자를 업데이트 할 것이고, 이유는 모르겠지만 그것이 실제로 느리다는 말을 들었습니다. 그러나 이것은 내 목적을 위해 충분해야한다.

+0

'System.Random'을 순수한 방식으로 사용할 수 있습니다 ([이 답변] (http://stackoverflow.com/questions/2110535/sampling-sequences-of-random-numbers-in-haskell/2125329 # 2125329). –

+0

어떤 일이 벌어지고 있는지 더 잘 이해할 수 있도록 함수에 형식 시그니처를 추가해야합니다. 또한 runState는 유형 (s, a)의 순수 값을 리턴합니다. 그런 식으로 "do"표현을 끝낼 수 없습니다. 순수 값이면 반환해야합니다. –

+0

runStateT는 모나드 변환기 용이고 runState는 일반 상태 모나드 용입니다. –

답변

1

나는이 폴 존슨보다 더 나은 대답하지만 난 당신이 원하는 것을 이해하면 그것을 할 수있는 방법 중 하나라고 실 거예요 : 나는했습니다 이후 표준 난수 발생기 모듈을 사용하고

import Control.Monad.State 
import System.Random 

-- utility function to hide plumbing of random generator types. 
rand :: (Random a, RandomGen g, MonadState g m) => a -> a -> m a 
rand lo hi = do 
    r <- get 
    let (val, r') = randomR (lo, hi) r 
    put r' 
    return val 

(flip runState) (mkStdGen seed) $ do 
    x <- rand 0 24 
    y <- rand 4 10 
    z <- rand 5 50 
    ... 
    ... 

을 random-fu를 사용하지는 않았지만 원칙이 동일해야합니다. 라이브러리에없는 경우에는 rand 작업을 수행해야합니다.

코드 유형을 일반으로 유지하기 위해 MonadState 유형 클래스의 인스턴스 인 모나드 (변압기)와 함께 사용할 수 있습니다. 타입 클래스를 사용할 필요가 없으며 원하는 경우 rand 유형에서 특정 모나드를 사용할 수 있습니다.

+0

pureMT를 사용하고 싶었던 이유는 상태 모나드에서 haskell의 일반 무작위 함수를 사용하려고하면 많은 것들이 느려지는 것을 들었기 때문입니다. 일반적인 시스템 무작위가 mersenne 트위스터보다 100 배 느린 것만이 아니라 모든 세대마다 게으른 상태로 돌연변이를 일으킬 수도 있습니다. 랜덤 - 푸 (random-fu)에서 어떻게 처리 될지 생각하기를 정말로 바랬습니다. 왜냐하면이 문제를 위해 설계된 것처럼 보였기 때문입니다. –

+0

@onmach 나는 두 가지 중 하나를 사용해서는 안되며 사용하지 말아야한다고 말하지는 않습니다. 나는 무작위 - 후 패키지에 대해 아무것도 모른다고 말하고 있습니다 만, 아마 이미 이런 행동을했을 것이라고 추측합니다. 당신은 자신이 원하는대로 행동을 취할 수 있도록 자신을 쓸 수 있어야합니다. 필자는 문서를 매우 간략하게 살펴 봤지만 PureMT에는 mkStdGen과 같은 시드를 사용하는 순수한 함수가 있음을 알았습니다 (현재 PureMT의 이름은 기억하지 못합니다). 지금 당장 편집 한 내용을 읽으면서 지금은 PureMT가 RandomGen 대신에 사용할 수있는 MonadRandom을 구현한다고 설명하고 있습니다. –

+0

@onmach 당신은 getRandomPrimFromMTState 함수를 원한다고 생각합니다. Data.Random.Source.PureMT 모듈의 문서를 확인하십시오. –

1

이렇게하려면 QuickCheck의 Gen 모나드를 사용하는 것이 좋습니다. 무작위 데이터 구조를 만들기 위해 설계되었으므로 던전을 데이터 구조로 정의한 다음이를 "임의의"인스턴스로 작성해야합니다 (QuickCheck 문서 참조).

당신의 생각은 "임의의 숫자를 얻어 지하 감옥으로 변환"하는 것 같습니다. 더 좋은 사고 방식은 "임의의 던전 요소를 생성하고 무작위로 함께 연결하는 것"입니다.

관련 문제