5

私はイライラする調査をしばらく行った後にこれを書いています。ここの誰かがこのトピックについて私を啓発してくれることを願っています.

Haskell関数で単純な乱数を生成したいのですが、残念ながら、モナド、「do」での代入、ジェネレーターの作成など、あらゆる種類の重要な要素なしではこれを行うことは不可能のようです.

理想的には、C の「rand()」に相当するものを探していました。しかし、よく調べた結果、言語がどのように設計されているかを考えると、そのようなことはないと確信しています。(もしあれば、誰か教えてください)。それは現実的ではないように思われるので、特定の問題に対して乱数を取得する方法と、乱数を取得する方法に関する一般的な説明を見つけたいと思います。

prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = frequency [ 
    (1, return ([],[])),
    (2, do {
            xs1 <- orderedListEj13 ;
            xs2 <- orderedListEj13 ;
            return (xs1,xs2)
       }),
    (2, do {                
            xs2 <- orderedListEj13 ;
            return ((take RANDOMNUMBERHERE xs2),xs2)
       })
    ]

私は QuickCheck を理解しようとしていますが、乱数を使用できないために難しくなっています。私はこのようなことを試しました RANDOMNUMBERHEREの代わりにdrawInt 0(長さxs2)を配置することにより)が、テイクにはIntが必要であり、そのメソッドにはIO Intが残っているという事実に行き詰まります。thisによると Int 。

4

3 に答える 3

7

haskell は純粋な関数型プログラミング言語であるため、関数は参照透過的です。これは、基本的に関数の引数のみがその結果を決定することを意味します。空中から乱数を引き出すことができた場合、それがどのように問題を引き起こすか想像できます。

次のようなものが必要だと思います:

prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = do
  randn <- choose (1,999) -- number in range 1-999
  frequency [ 
    (1, return ([],[])),
    (2, do {
            xs1 <- orderedListEj13 ;
            xs2 <- orderedListEj13 ;
            return (xs1,xs2)
       }),
    (2, do {                
            xs2 <- orderedListEj13 ;
            return ((take randn xs2),xs2)
       })
    ]

一般に、haskell では、IO モナドからランダム性を引き出すか、ハードコードされた整数シードで初期化された PRNG を維持するか、IO から引き出される (gspr のコメントは優れています) ことによって、乱数生成にアプローチします。

疑似乱数ジェネレーターがどのように機能するかについて読むSystem.Randomと、を理解するのに役立ちます

于 2012-03-16T20:40:15.483 に答える
4

非決定論的な乱数 (「疑似乱数」を意味します) の数の生成は、策略なしでは不可能です。Haskell の関数は純粋です。つまり、同じ入力は常に同じ出力を生成します。

幸いなことに、非決定論的な PRNG は必要ないようです。実際、テストを完全に再現可能にするために、QuickCheck テストで毎回同じ一連の「乱数」を使用した方がよいでしょう。

System.RandommkStdGenの関数を使用してこれを行うことができます。Haskell wikiからの適応:

import System.Random
import Data.List

randomInts :: Int -> [Int]
randomInts n = take n $ unfoldr (Just . random) (mkStdGen 4)

ここでは、公正なサイコロを振っ4て選択するシードを示します。

于 2012-03-16T20:39:49.063 に答える
3

標準ライブラリは、乱数生成用のモナドを提供します。モナドのことを学ぶのはそれほど難しくありませんが、それを避けたい場合は、疑似乱数の方法で から を受け取る疑似乱数関数nextを見つけてIntからInt、乱数の無限リストを作成して渡します。

next :: Int -> Int
randoms :: [Int]
randoms = iterate next 73

その後、この乱数のリストを必要な場所に渡すことができます。

nextウィキペディアの線形合同法は次のとおりです。

next n = (1103515245 * n + 12345) `mod` 1073741824

73 に続く最初の 20 個の疑似乱数を次に示します。

Prelude> take 20 $ iterate next 73
[73,25988430,339353199,182384508,910120965,1051209818,737424011,14815080,325218177,1034483750,267480167,394050068,4555453,647786674,916350979,980771712,491556281,584902142,110461279,160249772]
于 2012-03-17T01:39:03.860 に答える