7

Haskell が動的または静的スコープを使用しているかどうかを把握しようとしています。たとえば、次のように定義するとわかります。

let x = 10

次に、関数を定義します

let square x = x*x

2 つの異なる「x」がありますが、それは動的にスコープされているということですか? そうでない場合、どのスコープが使用され、その理由は?

また、Haskell 変数にエイリアス (同じメモリ位置/値の別の名前) を付けることはできますか?

ありがとう。

4

9 に答える 9

17

Haskell は (大まかに言えば) 他のほとんどの言語とまったく同じ字句スコープを使用します。

例えば。

x = 10

xグローバルスコープで参照される値になりますが、

square x = x * x

x字句的に関数 square にスコープされることになります。上記の形式が次の構文上の利点であると考えると、役立つ場合があります。

square = \ x -> x * x

あなたの他の質問については、エイリアシングの意味がわかりません

于 2008-12-02T06:09:50.010 に答える
7

質問の2番目の部分のみに答える:

同じ「メモリの場所」に複数のエイリアスを設定できますが、それらはすべて不変であるため、ほとんどの場合は問題になりません。

ばかげた例:

foo x y = x * y
bar z = foo z z

from内でfoo呼び出された場合barxyは明らかに同じ値です。しかし、 も も変更できないため、x気付かyないこともあります。

于 2008-12-02T10:57:42.050 に答える
6

あなたの声明にはいくつか間違っていることがあります...

  • Haskellには定義だけの可変変数(または不変変数)はありません
  • 可変メモリ位置は、Haskellには存在しない概念です

あなたの例では、関数のxは10ではありません。これはsquareの引数であり、この場合は10ですが、この場合は任意の値をとることができます(後でタイプを指定できます)。

CurtSampsonが提供するエイリアスの例を次に示します。

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42
于 2008-12-02T06:39:59.370 に答える
3

質問の最初の部分は他の人がすでに回答しているので、2番目の部分は次のとおりです。

私はaliasingあなたが意味すると思いますone name for another。haskell は関数型言語であり、関数はどのような場合でも通常の識別子として動作するため、次のようにできます。

y = x

y関数のエイリアスを定義しますx。すべてが関数であることに注意してください。"変数"のように見えても、引数を取らない単なる nullary 関数です。タイプのエイリアスは次のようになります。

type Function = Double -> Double

Functionタイプのエイリアスを定義しますDouble -> Double

于 2008-12-02T15:43:32.660 に答える
2

Haskellは静的なネストされたスコープを使用します。静的にネストされたスコープを持つ他の言語と比較して少し混乱するのは、名前のスコープがその定義の前にあるテストを含むブロックであるということです。例えば

evens = 0 : map (+1) odds
odds  = map : (+1) evens

ここで、「オッズ」という名前は、「オッズ」がまだ定義されていないという驚くべき事実にもかかわらず、「偶数」の定義の範囲内にあります。(この例では、偶数と奇数の2つの無限リストを定義しています。)

同様のスコープルールを持つ死語はModula-3でした。しかし、Haskellは、同じスコープ内で変数を「再定義」することができるという点で少し注意が必要ですが、代わりに別の再帰方程式を導入するだけです。これは、MLまたはSchemeを最初に学んだ人々にとっての落とし穴です。

let x = 2 * n
    x = x + 1   -- watch out!

これは完全に優れたMLまたはSchemelet*ですが、Haskelにはラムダ値に制限のないschemeletrecセマンティクスがあります。これがトリッキーなものであることは不思議ではありません!

于 2008-12-10T09:54:05.137 に答える
2

あなたの例では、 x のグローバル定義は x のローカル定義によって隠されています。Haskell では、変数のスコープはソース コードの静的読み取りによって決定されます。これはレキシカル スコープと呼ばれますが、暗黙的なパラメーターを使用した動的スコープに似たものを取得できます (ただし、予期しない動作につながる可能性があります (私は読んだ; 決して自分で試してみました))。

于 2008-12-02T15:46:09.830 に答える
1

他の答えを簡潔に要約するには:

  1. レキシカルスコープ
  2. エイリアシングは簡単ですがx = 1; y = x、物事は不変であるため、通常は問題になりません。

例で使用する構文は、対話型プロンプトletにあるように見えます。ghci>対話モードではすべてが IO モナド内で発生するため、そこでは通常よりも変更可能に見える場合があります。

于 2008-12-03T18:53:51.403 に答える
0

はい、Haskell にはエイリアスがあります。この小さなプログラムを試してください:

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42
于 2009-06-15T01:44:04.750 に答える
0

ええと、すでに皆さんが言っていると思いますが、Haskell には他のほとんどの言語に見られるような変数はなく、式しかありません。In your example let x = 10x is a expression that evaluates to always 10. 後で x の値を実際に変更することはできませんが、スコープ ルールを使用して x を別の式に定義することで非表示にすることはできます。

于 2008-12-07T20:59:01.100 に答える