5

グローバル環境 (ネイバー IP アドレスなどの特定の制約を定義する) が作成され、初期化関数を呼び出すことによって初期化されるモジュールがあります後続の関数の多くは、呼び出されたときにこれらの制約を使用する必要があります。

原則として、リーダーモナドが何をするかは理解していますが、これを自分の問題にどのように適用できるかはよくわかりません。

  • ユーザーによって定義され、データ/引数として初期化関数に渡される環境を初期化するために使用する方法。つまり、reader モナドは、グローバルな不変環境を構成する実際の値をどこかから取得する必要があります。myinitial :: arg1 -> arg1 -> IOStringその後、値がwhere のような初期化関数呼び出しから読み取られ、リーダーモナド (?) を介して後続の関数にアクセスできるグローバルな不変データになるarg1ことを望みます。arg2

  • これらの環境値を関数の引数として使用する方法、たとえば、環境からのグローバルな不変データはrecvFrom s arg1どこにありますか。arg1またはif arg2 > arg1 then ... else ...

もちろん、構成ファイルを作成することもできますが、構成ファイルを使用すると柔軟性が大幅に低下すると思います。

[編集] ask については理解していますが、関数シグネチャが正しく定義されている場合にグローバル/環境の不変を省略できるように、追加の「ポイントフリーのような」方法があるべきではありませんか? これを適用するには、どのように if-then-else をリファクタリングする必要がありますか。

4

2 に答える 2

5

質問のほとんどは、ask関数とrunReader関数の型とドキュメントを調べることで解決できます。

まず、ask:

ask :: Reader m r => m r

これは、モナドにラップされた基礎となる読み取り専用データを返します。クールなので、上記の例で、他の関数で使用したいときに状態に到達する方法は次のとおりです。

do x <- ask
   recvFrom s x

recvFrom(もちろんタイプにもよりますが)

次は ですrunReader。これは、あなたが話していた初期データを与える方法です。基本的には、Reader与えられたデータを使用して計算を実行するだけです:

runReader :: Reader r a -> r -> a

つまり、読み取り専用データ型r(2 番目の引数) を使用して計算 (最初の引数) を実行します。最後に、第 1 引数の結果の型を返しますa。あなたの場合、これは次のようになります。

result = runReader computationUsingArg1Arg2 (arg1, arg2)

次に、内部でcomputationUsingArg1Arg2読み取ることができます。arg1arg2ask

于 2012-06-13T00:29:50.450 に答える
4

これは物事をクリアするかもしれない例です。まず、Readerモジュールをインポートする必要があります。

import Control.Monad.Reader

次に、いくつかのデータ構造を定義しましょう(名前と年齢を保持するために使用します)

data Config = Config { name :: String, age :: Int }

次に、Readerモナドで機能する関数を定義します(そのタイプはですReader Config (String, Int)が、指定する必要はありません-推測できます)。この関数が行うのは、(タイプのConfig)環境を要求してから、フィールドを抽出し、それらを使用して何かを実行することだけです。

example = do
    c <- ask
    return ("Hello " ++ name c, 2 * age c)

これで、すべてを1つのプログラムにまとめました。doブロックの後の最初の4行で、ユーザーは名前と年齢を入力できます。次にConfig、ユーザーの入力を使用して構造を構築し(コンストラクターにフィードできるようにread、変数を変換するため_ageString使用する必要があります) 、関数を使用してこの環境で実行します。最後に、この計算の結果を使用して出力を生成します。IntConfigexamplerunReader

main = do
    putStrLn "Enter your name:"
    _name <- getLine
    putStrLn "Enter your age:"
    _age <- getLine
    let config = Config _name (read _age)
    let result = runReader example config
    putStrLn $ fst result
    putStrLn $ "Twice your age is: " ++ show (snd result)
于 2012-06-13T08:17:20.610 に答える