Haskellでは、既存の変数を変更することはできません。しかし、変数名を再利用することができます。これはすべてここで起こっています。
Prelude> let a = 1
Prelude> :i a
a :: Num a => a -- Defined at <interactive>:2:5
Prelude> let a = 2
Prelude> :i a
a :: Num a => a -- Defined at <interactive>:4:5
これらは実際には同じ名前を呼ばれるように起こる2全体の別々の、異なる変数、以下のとおりです。これを見るための一つの方法は、変数が宣言されました:i[nfo]
ディレクティブを使用して、GHCiのを依頼することです!あなただけa
を求める場合は、これを確認する1つの方法を新しい定義が“が”を優先されますが、古いものはまだそこ–で、コメントでカイで述べとして、関数内でa
を使用することです:
Prelude> let a = 2
Prelude> :i a
a :: Num a => a -- Defined at <interactive>:4:5
Prelude> let f x = a + x
Prelude> let a = 3
Prelude> f (-2)
0
f
a
とも呼ばれる新しい変数を定義したことに気にする必要はありません。その視点から、a
は常にそのままの1つの不変変数でした。
なぜGHCiが後の定義を好むのかについて少し話をする価値があります。これは、ではなく、がハスケルコードで起こることはありません。あなたは、以下のモジュールをコンパイルしようとした場合、特に、それは単に重複定義に関するエラーを与える:
a = 1
a = 2
main :: IO()
main = print a
このようなものは、GHCiの中で許可されていることを理由に、それはHaskellのモジュールは異なる動作することです。 GHCiコマンドのシーケンスは、事実上、IOモナドアクションのシーケンスを形成します。&dagger;;プログラムは
今
main :: IO()
main = do
let a = 1
let a = 2
print a
でなければならないであろう。すなわち、あなたがモナドについて学んできた場合、あなたはこれが
main =
let a = 1 in (let a = 2 in (print a))
のためだけの構文糖であり、これは本当に、なぜにとって極めて重要ビットであることを知っていますよa
という名前をもう一度使用することができます。第2のものは、a = 2
です。が狭い範囲にあります。が最初のものより長くなります。したがって、よりローカルであり、ローカル定義が優先されます。これが良い考えかどうかは議論の余地があります。それはあなたが
greet :: String -> IO()
greet name = putStrLn $ "Hello, "++name++"!"
のような機能を持たせることができる、それはあなたが“再定義をできることを実際にはかなり便利です、ほかに誰か他の場所で
name :: Car -> String
name car | rollsOverAtRightTurn car = "Reliant Robin"
| fuelConsumption car > 50*litrePer100km
= "Hummer"
| ... = ...
定義するという理由だけで、それは動作を停止しないことであるために良いの引数”変数はGHCiで欺かれていますが、ではありません。これは、一貫した動作を示すはずの適切なプログラムで再定義するような良い考えです。
; dfeuerの発言として、これは完全な真実ではありません。 IO
do-blockで許可されていないGHCiでいくつかのことを行うことができます。特に、data
のタイプとclass
を定義できます。しかし、通常のステートメントや変数定義は、モナドのIO
と同じように動作します。あなたが実際に見ることができるように
私の周りではうまくいきません。 – Netwave
'a = 1; '.hs'ファイルの中で' a = 2'を実行し、 'ghc'を使ってコンパイルします... – Bakuriu
GHCiコマンドはIOアクションなので、入力したものが' do'ブロックの中にある場合と似ています。つまり、同じ名前への後続の代入は、ネストされた 'let'sのようなものであり、あなたは古いバインディングです。 – Bakuriu