9

これを行う最良の方法は何ですか?unsafePerformIO? テンプレート Haskell? 他の何か?どちらも使ったことがないので、詳しい使い方はわかりません。

プログラムは実行されるたびにコンパイルされるため、コンパイル時または実行時に文字列を生成するかどうかは問題ではないことに注意してください。また、コード全体の多くの場所でこの文字列を使用する必要があるため、実際には「適切な」方法でそれを行うことができず、それを IO アクションにすることはできません。IO モナドに他のコードをあまりにも多く配置する必要があります。 .

4

6 に答える 6

4

で乱数を生成するIOことは、下流の関数が を使用しなければならないことを意味するものではありませんIO

type の値に依存する純粋関数の例を次に示しますA

f :: A -> B

...そして、これは以下IOを生成するアクションですA:

io :: IO A

f使用するために変更する必要はありませんIO。代わりに、次を使用しますfmap

fmap f io :: IO B

これはまさに、ファンクタが解決するはずの問題です: モーフィズムを変更する必要がないように、ラップされた値に対してモーフィズムを持ち上げます。

于 2013-07-06T13:46:53.797 に答える
4

ドキュメントが言うように、この特定のケースでの使用unsafeperformIOは問題ないようです:

これが安全であるためには、IO 計算は副作用がなく、その環境から独立している必要があります。

の順序は気にしませんnewStdGen

import System.Random
import System.IO.Unsafe

randomStr :: String
randomStr = take 10 $ randomRs ('a','z') $ unsafePerformIO newStdGen

main = do
     putStrLn randomStr
     putStrLn randomStr
于 2013-07-06T06:37:57.803 に答える
1
import System.Random

main = do
   gen <- newStdGen
   let str = take 10 $ randomRs ('a','z') gen 

   putStrLn str

   putStrLn $ (reverse . (take 3)) str

これにより、小文字のみの 10 文字の長さの文字列が生成されます。このコードは IO モナドにありますが、str は純粋であり、純粋な関数に渡すことができます。IO モナドがなければ、ランダムなものを取得することはできません。unsafePerformIO を実行できますが、その理由はよくわかりません。常に同じ値が必要な場合は、str 値を渡すことができます。私のコードの最後の行を見ると、文字列を操作する純粋な関数があることがわかりますが、それを見たいのでputStrLn、空の IO アクションを返す呼び出しを行っています。

編集: または、これは Reader モナドの場所かもしれません

于 2013-07-06T06:15:08.057 に答える
0

文字列、数値などの場合:

import System.Random ( newStdGen, randomRs, randomRIO )

main :: IO ()
main = do
    s <- randomString 8 ""
    putStrLn s
randomString :: Integer -> String -> IO String
randomString 0 str = return str
randomString size str = do
    g <- newStdGen
    t <- randomRIO ( 0, 2 )
    let s = take 1 $ randomRs ( range t ) g
    randomString ( size - 1 ) ( str ++ s )
    
    where
        range :: Integer -> ( Char, Char )
        range i
            | i == 0 = ('0', '9')
            | i == 1 = ('A', 'Z')
            | otherwise = ('a', 'z')
于 2021-08-14T14:53:21.503 に答える