2017-03-14 7 views
1

ここに私の問題の簡略化されたバージョンです:各連続した値が前のものに依存するランダムな値のリストを生成します。変換リスト(ジェネレータa)をジェネレータ(リストa)

たとえば、ランダムなリストIntを生成します。このリストでは、連続する各値が次のステップの最小値を設定します。

    1. まずステップ:のは value = 0と最大値を起動は常に currentValue + 5であると仮定する Random.int 0 5 => 3
    2. 次へ=> 4 Random.int 3 8
    3. 次へ=> 8 Random.int 4 9

    私のアプローチは次のとおりです。

    intGen : Int -> List (Rnd.Generator Int) -> List (Rnd.Generator Int) 
    intGen value list = 
        if length list == 10 then 
        list 
        else 
        let newValue = Rnd.int value (value + 5) 
         newList = newValue :: list 
        in intGen newValue newList 
    

    のはRnd.Generator (List Int)に変換してみましょう:(Rnd.list 0 (Rnd.int 0 1)):私はこの部分を好きではない

    listToGen : List (Rnd.Generator Int) -> Rnd.Generator (List Int) 
    listToGen list = 
        foldr 
        (Rnd.map2 (::)) 
        (Rnd.list 0 (Rnd.int 0 1)) 
        list 
    

    Rnd.Generator (List Int)の初期値を生成します。(Rnd.int 0 1)は実際には使用されませんが、型チェックでは必要です。私は何とかこの部分をスキップするか、より一般的なものに置き換えたいと思います。それが可能か、私の実装は間違っていますか?

  • 答えて

    3

    ここにandThenmapを使用する1つのソリューションです。最初のパラメータは、リストに含める要素の数です。 2番目のパラメータは開始値です。

    intGen : Int -> Int -> Rnd.Generator (List Int) 
    intGen num value = 
        if num <= 0 then 
         constant [] 
        else 
         Rnd.int value (value + 5) 
          |> Rnd.andThen (\i -> intGen (num-1) i 
          |> Rnd.map (\rest -> i :: rest)) 
    

    第一の低値として0から始まるサイズ10のリストのあなたの例を一致させるには、あなたがintGen 10 0としてこれを呼び出します。

    constantelm-community/random-extraから発電機である、または(それがコアエルムのコードベースで公開されていないため)、それは単純に次のように定義することができます

    constant : a -> Rnd.Generator a 
    constant a = Rnd.map (\_ -> a) (Rnd.int 0 1) 
    

    あなたの例については、私はあなたを考えていませんList (Rnd.Generator Int)を使用したがっているのは、どのような方法でも結びついていないジェネレータのリストを意味するためです。そのため、andThenを使用して、生成されたランダム値を引き出し、intGenを再帰的に1を差し引いて呼び出し、次にmapを使用してリストをまとめる必要があります。

    +0

    私は同様のことを考えていました。さらに、 'random-extra'パッケージには' List(Generator a) - > Generator(List a) '関数もありますので、コミュニティパッケージを知っておくと良いでしょう。ありがとう! – mmalik

    関連する問題