Haskellのアプローチを説明します(Haskellの専門家ではないため、直感が100%正しいかどうかはわかりませんが、修正は歓迎されます)。
コードは次のようにHaskellで記述できます。
import System.CPUTime
f :: Integer -> Integer -> IO Integer
f a b = do
t <- getCPUTime
return (a + b + (div t 1000000000000))
では、参照の透明性はどこにあるのでしょうか?
f
2つの整数a
とを指定するとb
、戻り値の型でわかるように、アクションを作成する関数ですIO Integer
。2つの整数が与えられた場合、このアクションは常に同じであるため、整数のペアをIOアクションにマッピングする関数は参照的に透過的です。
このアクションが実行されると、生成される整数値は現在のCPU時間に依存します。アクションの実行は機能アプリケーションではありません。
要約:Haskellでは、純粋な関数を使用して、複雑なアクション(シーケンス処理、アクションの作成など)を参照透過的な方法で構築および結合できます。ここでも、上記の例では、純粋な関数f
は整数を返さないことに注意してください。アクションを返します。
編集
JohnDoDo質問に関する詳細。
「アクションの実行が機能適用ではない」とはどういう意味ですか?
T1、T2、Tn、Tのセットが与えられた場合、関数fは、T1 x T2 x ... x Tnの各タプルにTの1つの値を関連付けるマッピング(関係)です。したがって、関数アプリケーションは、いくつかの入力値を指定して出力値を生成します。このメカニズムを使用すると、値を評価する式を作成できます。たとえば、値10
は式を評価した結果です4 + 6
。この方法で値を値にマッピングする場合、いかなる種類の入力/出力も実行しないことに注意してください。
Haskellでは、アクションは特別なタイプの値であり、アクションを操作する適切な純粋な関数を含む式を評価することによって構築できます。このように、Haskellプログラムは、main
関数を評価することによって取得される複合アクションです。このメインアクションにはタイプがありIO ()
ます。
この複合アクションが定義されると、別のメカニズム(関数アプリケーションではない)がアクションの呼び出し/実行に使用されます(ここを参照)。プログラム全体の実行は、サブアクションを呼び出すことができるメインアクションを呼び出した結果です。この呼び出しメカニズム(内部的な詳細は不明)は、必要なすべてのIO呼び出しを実行し、場合によっては端末、ディスク、ネットワークなどにアクセスします。
例に戻ります。上記の関数f
は整数を返さないため、IOを実行して同時に整数を返す関数を作成することはできません。2つのうち1つを選択する必要があります。
できることは、によって返されたアクションをf 2 3
より複雑なアクションに埋め込むことです。たとえば、そのアクションによって生成された整数を出力する場合は、次のように書くことができます。
main :: IO ()
main = do
x <- f 2 3
putStrLn (show x)
do
表記はメイン関数によって返されたアクションは、2つの小さい方のアクションの連続合成により得られることを示し、x <-
表記は最初のアクションで生成値が第2のアクションに渡さなければならないことを示しています。
2番目のアクションで
putStrLn (show x)
名前x
は、アクションの実行によって生成された整数にバインドされます
f 2 3
重要な点は、最初のアクションが呼び出されたときに生成される整数はIOアクション内にのみ存在できることです。これは、あるIOアクションから次のIOアクションに渡すことができますが、プレーン整数値として抽出することはできません。
main
上記の関数と次の関数を比較してください:
main = do
let y = 2 + 3
putStrLn (show y)
この場合、アクションは1つしかありません。つまりputStrLn (show y)
、y
純粋な関数を適用した結果にバインドされます+
。このメインアクションを次のように定義することもできます。
main = putStrLn "5"
したがって、構文が異なることに注意してください
x <- f 2 3 -- Inject the value produced by an action into
-- the following IO actions.
-- The value may depend on when the action is
-- actually executed. What happens when the action is
-- executed is not known here: it may get user input,
-- access the disk, the network, the system clock, etc.
let y = 2 + 3 -- Bind y to the result of applying the pure function `+`
-- to the arguments 2 and 3.
-- The value depends only on the arguments 2 and 3.
概要
- Haskellでは、純粋な関数を使用して、プログラムを構成するアクションを構築します。
- アクションは特別なタイプの値です。
- アクションは純粋な関数を適用することによって構築されるため、アクションの構築は参照に対して透過的です。
- アクションが作成されたら、別のメカニズムを使用して呼び出すことができます。