What type of scope does Haskell use?

2019-04-28 03:04发布

I'm trying to figure out if Haskell uses dynamic or static scoping. I realize that, for example, if you define:

let x = 10

then define the function

let square x = x*x

You have 2 different "x's", and does that mean it is dynamically scoped? If not, what scoping does it use, and why?

Also, can Haskell variables have aliases (a different name for the same memory location/value)?

Thanks.

9条回答
劫难
2楼-- · 2019-04-28 03:30

There are some things wrong in your statements...

  • There are no mutable variables in Haskell just definitions (or immutable variables)
  • A variable memory location is a concept that do not exist in Haskell

In your example, x is not 10 in the function is just a argument to square, that can take any value (you can specify the type later) in this case 10 but just in this case.

Here is an example of aliases provided by Curt Sampson:

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
查看更多
男人必须洒脱
3楼-- · 2019-04-28 03:34

As the first part of the question is already answered by others, here is the second part:

I assume by aliasing you mean one name for another. As haskell is a functional language, and functions behave as normal identifiers in any case, you can do that like this:

y = x

which would define an alias y for the function x. Note that everything is a function. Even if it looks like a "variable", it's just a nullary function taking no arguments. Aliases for types look like this:

type Function = Double -> Double

which would define an alias Function for the type Double -> Double

查看更多
何必那么认真
4楼-- · 2019-04-28 03:39

Haskell uses static nested scopes. What is a bit confusing compared with other languages that have static nested scopes is that the scope of a name is a block which includes tests preceding its definition. For example

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

here the name 'odds' is in scope in the definition of 'evens', despite the surprising fact that 'odds' has not yet been defined. (The example defines two infinite lists of even and odd numbers.)

A dead language with a similar scoping rule was Modula-3. But Haskell is a bit trickier in that you can attempt to 'redefine' a variable within the same scope but instead you just introduce another recursion equation. This is a pitfall for people who learned ML or Scheme first:

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

This is perfectly good ML or Scheme let*, but Haskel has scheme letrec semantics, without the restriction to lambda values. No wonder this is tricky stuff!

查看更多
干净又极端
5楼-- · 2019-04-28 03:40

To sum up the other answers concisely:

  1. lexical scope
  2. aliasing is as easy as x = 1; y = x but doesn't usually matter because things are immutable.

The let syntax you use in your example looks like it's at the interactive ghci> prompt. Everything in interactive mode occurs within the IO monad so things may appear more mutable there than normal.

查看更多
走好不送
6楼-- · 2019-04-28 03:43

Answering only the second part of the question:

You can have several aliases for the same "memory location", but since they are all immutable, it does not matter most of the time.

Dumb example:

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

When within foo called from bar, both x and y are clearly the same value. But since you cannot modify either x or y, you will not even notice.

查看更多
手持菜刀,她持情操
7楼-- · 2019-04-28 03:43

Well, as I think people have said already, Haskell doesn't have any variables as found in most other languages, it only has expressions. In your example let x = 10 x is an expression that always evaluates to 10. You can't actually change the value of x later on, though you can use the scoping rules to hide it by defining x to be another expression.

查看更多
登录 后发表回答