1

変更可能な変数を格納するために、IORef を使用して Haskell で単純な乱数ジェネレーターを作成しようとしています。アイデアは、シードを初期化し、シードに基づいて数値を生成し、次のランダムな int 用に新しいシードを格納できるというものです。

私が得ている完全なエラーは次のとおりです。

random2.hs:9:17:
    Couldn't match type `IO Int' with `Int'
    Expected type: IO (IORef Integer)
                   -> (IORef Integer -> IO Int) -> Int
      Actual type: IO (IORef Integer)
                   -> (IORef Integer -> IO Int) -> IO Int
    In a stmt of a 'do' block: seed <- newIORef 7
    In the expression:
      do { seed <- newIORef 7;
           randomGen (readIORef seed) }
    In an equation for `getRandom':
        getRandom
          = do { seed <- newIORef 7;
                 randomGen (readIORef seed) }

random2.hs:10:17:
    Couldn't match type `(,) Int' with `IO'
    Expected type: IO Int
      Actual type: (Int, Int)
    In the return type of a call of `randomGen'
    In a stmt of a 'do' block: randomGen (readIORef seed)
    In the expression:
      do { seed <- newIORef 7;
           randomGen (readIORef seed) }

random2.hs:10:28:
    Couldn't match expected type `Int' with actual type `IO Integer'
    In the return type of a call of `readIORef'
    In the first argument of `randomGen', namely `(readIORef seed)'
    In a stmt of a 'do' block: randomGen (readIORef seed)
Failed, modules loaded: none.

タイプと一致しない方法がわかりません-randomGenがIntを受け取る/返すことを明示しています。これが私のコードです:

module Main where
    import Data.IORef

    randomGen :: Int -> (Int, Int)
    randomGen x = (x,x+1)

    getRandom :: Int
    getRandom = do
        seed <- newIORef 7
        randomGen (readIORef seed)

ここで何が起こっているのか分かりますか?

ありがとう、

更新されたコード:

module Main where
    import Data.IORef
    import Control.Monad

    randomGen :: Int -> (Int, Int)
    randomGen x = (x,x+1)

    getRandom :: IO Int
    getRandom = do
        seed <- newIORef 7
        liftM (fst (randomGen (readIORef seed)))
4

2 に答える 2

3

タイプIO IntIntは、Haskell ではまったく異なります。Maybe Intこれは、やなど、そのフォームの他のタイプに適用されますEither String Int。これは Haskell の型システム設計の一部であり、非常に強力です。この形式のあらゆるものを一種のコンテナーと考え​​ることができ、その型でパラメーター化されます。したがって、次のようなことができます

getRandom :: IO Int
getRandom = do
    seed <- newIORef 7           -- IO (IORef Int)
    g <- readIORef seed          -- IO Int
    let (x, newG) = randomGen g  -- (Int, Int)
    writeIORef seed newG         -- IO ()
    return x                     -- IO Int

ただし、シードは呼び出しごとに破棄されるため、これは常に同じ値を返します。MonadRandom パッケージには素晴らしい API があるのに、なぜ乱数を生成するためにこのアプローチを採用したいのか、興味があります。モナドの使用方法の例については、私がしばらく前に書いたこの回答を参照してください。また、モナドがどのように機能するかについてのもう少し詳細な説明については、この回答を参照してください。Rand

于 2014-05-12T20:19:46.677 に答える