56940


HaskellのStateTの使い方を理解するため、  
乱数の上限値を保存するコードを書こうとしているのですが、いまいち分りません。以下現在のコードです

[code]

    import System.Random
    import Control.Monad.State
    
    getRandom :: Int -> IO Int
    getRandom x = getStdRandom $ randomR (0,x)
    
    getCurrent :: StateT Int IO Int
    getCurrent = do
      i <- get
      x <- lift $ getRandom i
      return x
    
    updateMax :: x -> StateT Int IO ()
    updateMax x = do
      put x
    
    main = do
      a <- flip evalState 0 $ do
        updateMax 1000
        getCurrent
      print a
    
[/code]

どうなれば上限値を更新・保存するように出来るでしょうか？

命令型ならこんな感じのコードになると思います。

[code]

    Max = 0;
    func getRandom = RandRange(0,Max);
    
    
    func main = {
      Max=100;
      print(getRandom()); // 出力 50 等
      Max=1000;
      print(getRandom()); // 出力 500 等
    }
    
[/code]


CC BY-SA 4.0
2019-07-27T05:45:05.017
56937
2019-07-27T12:07:43.027
2019-07-27T07:50:28.793
19620
19620
question
haskell
haskell StateTの使い方を知りたい(乱数の最大値を保存するコードを書きたい)


  1. 「Couldn't match type ‘x’ with ‘Int’」というエラーメッセージの通り、`put`によって`StateT Int`の`Int`という具体的な方の値を更新しようとしているにもかかわらず、`x`を指定してしまっています。
  2. 「Couldn't match type ‘IO’ with ‘Data.Functor.Identity.Identity’」というエラーメッセージのとおり、`evalStateT`を使うべきところで`evalState`を使ってしまっています。（`type State s = StateT s Identity`という定義なのを覚えておいてください！）

以上を解決すれば、意図通りに動作するはずです。

* * *

以下は古い回答です。いただいたコメントとの整合性をとるために一応残しておきます。

`updateMax` のところで「`x`が現在保存している値（`get`で取得できる値）より大きければ更新する」というロジックを加えるのがポイントです。  
難しければ、ほかのプログラミング言語で命令型のアルゴリズムで試しに書いてみると分かりやすいかも知れません。  
`StateT` はそうした命令型のアルゴリズムを翻訳するのにも使えるので。


CC BY-SA 4.0
2019-07-27T06:48:47.297
56940
2019-07-27T08:35:40.560
2019-07-27T08:35:40.560
8007
8007
56937
answer


自己解決しました。  
<https://wiki.haskell.org/Simple_StateT_use>  
を参照しました

[code]

    import System.Random
    import Control.Monad.State
    
    type MaxState a = StateT Int IO a
    
    getRandom :: Int -> IO Int
    getRandom x = getStdRandom $ randomR (0,x)
    
    getCurrent :: MaxState Int
    getCurrent = do
      i <- get
      x <- lift $ getRandom i
      return x
    
    updateMax :: Int -> MaxState ()
    updateMax x = do
      a <- get
      put x
    
    process :: MaxState Int
    process = do
      updateMax 10
      a <- getCurrent
      liftIO $ print a
      updateMax 10000
      b <- getCurrent
      liftIO $ print b
      return b
    
    main :: IO ()
    main = do
      x <- runStateT process 1
      print x
    
[/code]


CC BY-SA 4.0
2019-07-27T12:07:43.027
56944
2019-07-27T12:07:43.027
19620
56937
answer