difference between variable definition in a Haskell source file and in GHCi? - haskell

In a Haskell source file, I can write
a = 1
and I had the impression that I have to write the same in GHCi as
let a = 1
, for a = 1 in GHCi gives a parse error on =.
Now, if I write
a = 1
a = 2
in a source file, I will get an error about Multiple declaration of a, but it is OK to write in GHCi:
let a = 1
let a = 2
Can someone help clarify the difference between the two styles?

Successive let "statements" in the interactive interpreter are really the equivalent of nested let expressions. They behave as if there is an implied in following the assignment, and the rest of the interpreter session comprises the body of the let. That is
>>> let a = 1
>>> let a = 1
>>> print a
is the same as
let a = 1 in
let a = 1 in
print a

There is a key difference in Haskell in having two definitions of the same name and identical scopes, and having two definitions of the same name in nested scopes. GHCi vs modules in a file isn't really related to the underlying concept here, but those situations do lead you to encounter problems if you're not familiar with it.
A let-expression (and a let-statement in a do block) creates a set of bindings with the same scope, not just a single binding. For example, as an expression:
let a = True
a = False
in a
Or with braces and semicolons (more convenient to paste into GHCi without turning on multi-line mode):
let { a = True; a = False} in a
This will fail, whether in a module or in GHCi. There cannot be a single variable a that is both True and False, and there can't be two separate variables named a in the same scope (or it would be impossible to know which one was being referred to by the source text a).
The variables in a single binding set are all defined "at once"; the order they're written in is not relevant at all. You can see this because it's possible to define mututally-recursive bindings that all refer to each other, and couldn't possibly be defined one-at-a-time in any order:
λ let a = True : b
| b = False : a
| in take 10 a
[True,False,True,False,True,False,True,False,True,False]
it :: [Bool]
Here I've defined an infinite list of alternating True and False, and used it to come up with a finite result.
A Haskell module is a single scope, containing all the definitions in the file. Exactly as in a let-expression with multiple bindings, all the definitions "happen at once"1; they're only in a particular order because writing them down in a file inevitably introduces an order. So in a module this:
a = True
a = False
gives you an error, as you've seen.
In a do-block you have let-statements rather than let-expressions.2 These don't have an in part since they just scope over the entire rest of the do-block.3 GHCi commands are very like entering statements in an IO do-block, so you have the same option there, and that's what you're using in your example.
However your example has two let-bindings, not one. So there are two separate variables named a defined in two separate scopes.
Haskell doesn't care (almost ever) about the written order of different definitions, but it does care about the "nesting order" of nested scopes; the rule is that when you refer to a variable a, you get the inner-most definition of a whose scope contains the reference.4
As an aside, hiding an outer-scope name by reusing a name in an inner scope is known as shadowing (we say the inner definition shadows the outer one). It's a useful general programming term to know, since the concept comes up in many languages.
So it's not that the rules about when you can define a name twice are different in GHCi vs a module, its just that the different context makes different things easier.
If you want to put a bunch of definitions in a module, the easy thing to do is make them all top-level definitions, which all have the same scope (the whole module) and so you get an error if you use the same name twice. You have to work a bit more to nest the definitions.
In GHCi you're entering commands one-at-a-time, and it's more work to use multi-line commands or braces-and-semicolon style, so the easy thing when you want to enter several definitions is to use several let statements, and so you end up shadowing earlier definitions if you reuse names.5 You have to more deliberately try to actually enter multiple names in the same scope.
1 Or more accurately the bindings "just are" without any notion of "the time at which they happen" at all.
2 Or rather: you have let-statements as well as let-expressions, since statements are mostly made up of expressions and a let-expression is always valid as an expression.
3 You can see this as a general rule that later statements in a do-block are conceptually nested inside all earlier statements, since that's what they mean when you translate them to monadic operations; indeed let-statements are actually translated to let-expressions with the rest of the do-block inside the in part.
4 It's not ambiguous like two variables with the same name in the same scope would be, though it is impossible to refer to any further-out definitions.
5 And note that anything you've previously defined referring to the name before the shadowing will still behave exactly as it did before, referring to the previous name. This includes functions that return the value of the variable. It's easiest to understand shadowing as introducing a different variable that happens to have the same name as an earlier one, rather than trying to understand it as actually changing what the earlier variable name refers to.

Related

cfg attribute with arbitrary constant expression

I have the following const:
const IS_WSL: bool = is_wsl!();
and I'd like to be able to use this with the cfg attibute to perform conditional compilation. Something like:
#[cfg(const = "IS_WSL")] // what goes here?
const DOWNLOLADS: &'static str = "/mnt/c/Users/foo/Downloads";
#[cfg(not(const = "IS_WSL"))]
const DOWNLOADS: &'static str = "/home/foo/Downloads";
Obviously this syntax doesn't work, but is there any way to achieve what I'm describing?
I'm aware of custom rustc flags, but would like to avoid doing that, since there's a fair amount of logic that I'd rather not try to write in bash
The answer is not. You have to use something like build script to achieve that.
It cannot work because cfg-expansion occurs at an earlier pass in the compiler than constant evaluation.
cfg expansion works at the same time as macro expansion. Both can affect name resolution (macros can create new names, which other macros, or even the same macro, can later refer to) which forces us to use a fixed-point algorithm (resolve names, expand macros, resolve names, expand macros... until no more names can be resolved, i.e. a fixed point was reached). const evaluation takes a place after type checking, sometimes (with generic_const_exprs) even during codegen. If it could affect macro expansion, we would have a giant fixed-point loop resolve names - expand macros - resolve names - expand macros... until a fixed point is reached, then lower to HIR - type-check - evaluate constants (or even lower to MIR - monomorphize and evaluate constants) - and back to name resolution. Besides slowing the compiler down a lot, it'll also make it significantly more complex, not really something the rustc team wants.
In your specific case, since both cfg variants declare a static with the same name and type you can just match on IS_WSL:
const IS_WSL: bool = is_wsl!();
const DOWNLOADS: &'static str = match IS_WSL {
true => "/mnt/c/Users/foo/Downloads",
false => "/home/foo/Downloads",
};
Playground
This doesn't have the same power as cfg does, but it is still useful if you just need to select two values of the same type.

Syntax rules for Haskell infix datatype constructors

I'm trying to make a Haskell datatype a bit like a python dictionary, a ruby hash or a javascript object, in which a string is linked to a value, like so:
data Entry t = Entry String t
type Dictionary t = [Entry t]
The above code works fine. However, I would like a slightly nicer constructor, so I tried defining it like this:
data Entry t = String ~> t
This failed. I tried this:
data Entry t = [Char] ~> t
Again, it failed. I know that ~ has special meaning in Haskell, and GHCi still permits the operator ~>, but I still tried one other way:
data Entry t = [Char] & t
And yet another failure due to parse error. I find this confusing because, for some inexplicable reason, this works:
data Entry t = String :> t
Does this mean that there are certain rules for what characters may occur in infix type constructors, or is it a cast of misinterpretation. I'm not a newbie in Haskell, and I'm aware that it would be more idiomatic to use the first constructor, but this one's stumping me, and it seems to be an important part of Haskell that I'm missing.
Any operator that starts with a colon : is a type constructor or a data constructor, with the exception of (->). If you want the tilde, you could use :~>, but you're not going to get away with using something that doesn't start with a colon. Source

i'm confused about languages category, can anyone please explain?

Which of the following statements is FALSE?
(A) In statically typed languages, each variable in a program has a fixed type
(B) In un-typed languages, values do not have any types
(C) In dynamically typed languages, variables have no types
(D) In all statically typed languages, each variable in a program is associated with values of only a single type during the execution of the program
Can you please explain the theory as well?
C) (In dynamically typed languages, variables have no types) Is false.
The variable has a type, however it is simply not stated or decided until run time. This implies there is no type checking prior to running the program.
a useful link describing Types and what it means:
http://en.wikipedia.org/wiki/Type_system
If you have ever done much with PHP you will notice that when you declare a varialbe, you do not have to say whether it is an INT or a STRING. However, sometimes you know that you will be receiving a string, but need an int, so you can still type cast variables at runtime, even though when you declared the variable you did not explicitly state the variable would hold an int.
<?php
#some more code here.....
# over here $myValue could be of some different type, but it can dynamically change to another type
$myValue = '5'; #storing a string...so $myValue is currently of type String
$myNewValue = (int)$myValue + 5 #type casted to integer, so in this case $myValue is currently of type integer
?>
If that doesn't help, maybe take a look at this.
myPythonVariable = "I am currently a string" #the variable is of type string
myPythonVariable = 5 #the variable is now of type integer
In the above code sample, myPythonVariable always has a type, whether or not that type changes doesn't matter.

ghci: keep defined values in scope after module reload

I am wondering if it is possible to keep assigned values in ghci when a module is reloaded?
For example i assign a value in ghci:
ghci> let x = 1
or
ghci> x <- getLine
After entering :r to reload an existing module x is not in scope anymore. Is it generally possible to keep the assignment available, like for example in the Python interpreter? (this is really convenient...)
Even tho that actually each line in ghci represents a function that is (monadically) bound to the next one I am still wondering if maintaining that state is possible.
I'm not aware of any way of doing this.
The trouble is that you could have some variable bound to a value of a certain type, edit the source to remove that type, and hit reload. Now you have a variable of a type that no longer exists.
Still, you would think it shouldn't be too hard to detect that, and discard just the variables that don't make sense any more. (The really fun part is presumably when a type still exists but has a different number of fields now, or something like that...)

Calling a function in Haskell - beginner problem

Just started learning Haskell.
I have an empty source file with this inside:
pe :: (Integral a) => a -> a
pe y = sum [x | x <- [1..y-1], x `mod` 3 == 0 || x `mod` 5 == 0]
Now if I ghci this, I can call pe like so:
*Main> pe 1000
233168
How do I call it from within my source file? If I have
pe 1000
it returns a cryptic error:
GHC stage restriction: `pe'
is used in a top-level splice or annotation,
and must be imported, not defined locally
In the expression: pe 1000
Do I need to declare it in main or something?
Yes, you need to hook it up to your main function. For example,
main = print (pe 1000)
If you want to have multiple calls, you can combine them with do-notation:
main = do
print (pe 500)
print (pe 1000)
A Haskell source file contains a sequence of definitions, not expressions. So you can't just put an expression in the top level of the file, you have to put it inside the body of a definition. So since pe 1000 is not a definition, you get an error.
But why such a cryptic error message? GHC has an extension called Template Haskell, which allows you to programmatically create definitions at compile time. To achieve this it allows you to put an expression in a place where usually only definitions are allowed and evaluates the expression at compile time and replace the expression with its result (which must be a definition) - this is called splicing and the expression is then called a splice. Such a splice needs to meet two requirements:
Any identifiers used in the expression must be defined in a different source file (this is required so that the used functions are already compiled when the expression is encountered and thus can be called during compile-time)
The type of the expression must be a Template Haskell type which represents a valid definition.
So since your expression pe 1000 appears somewhere where only definitions are allowed, GHC assumes it is a splice. However since it does not meet the first of the above criteria, i.e. it is defined in the current file instead of a different file, GHC complains about that. Of course it doesn't meet the second condition either, but GHC hasn't gotten to that yet, when it produces the error message. If pe were defined in a different source file, you'd have gotten an error message complaining about the fact that pe has the wrong type.

Resources