I do not understand the difference between the three syntaxes:
where a = f (b)
do a <- f (b)
do let a = f (b)
I do understand somehow though that a <- f(b) is different from the other two, in most cases where I tried all three worked. Also I read somewhere on the net that per block you should try to get along with one let binding only in order to be "idiomatic". But I never seem to manage.
How do I decide what to use?
let foo = bar in ... simply defines foo to be the exact same thing as bar within the context of ...; you could simply use textual substitution to replace all uses of foo in ... with (bar) and get the exact same result.
where clauses are similar to let...in expressions, but go at the end of a function clause, instead of being an expression. For instance,
foo x
| p1 = ... y ...
| p2 = ... y ...
where
y = ...
There is no way to rewrite this with let...in without changing the guards into if...then...elses. Often, where clauses are used over let...in clauses purely for reasons of style.
The bind operator is something different entirely. It's used in do notation to "extract" a value from a monadic computation. That is, if foo has the type m a, then after x <- foo, x has the type a. All the other "binding" forms just define names, but <- is used for binding a computation's result to a name from within a monad. <- can only be used inside a do block, so it's exclusively used to build up a larger computation in the same monad as the action you're binding the result of.
let foo = bar in do notation is just a convenience; you can rewrite:
do let foo = bar
...
as
let foo = bar
in do ...
but that gets messy when you have a lot of such bindings, as the do blocks get nested deeper and deeper.
I don't know what the advice you mentioned is talking about; you can define multiple variables in a let...in block just fine, and
let foo = ...
bar ...
in ...
is more idiomatic than
let foo = ...
in let bar = ...
in ...
Related
I'm having some trouble defining a function in Frege that uses multiple patterns. Basically, I'm defining a mapping by iterating through a list of tuples. I've simplified it down to the following:
foo :: a -> [(a, b)] -> b
foo _ [] = [] --nothing found
foo bar (baz, zab):foobar
| bar == baz = zab
| otherwise = foo bar foobar
I get the following error:
E morse.fr:3: redefinition of `foo` introduced line 2
I've seen other examples like this that do use multiple patterns in a function definition, so I don't know what I'm doing wrong. Why am I getting an error here? I'm new to Frege (and new to Haskell), so there may be something simple I'm missing, but I really don't think this should be a problem.
I'm compiling with version 3.24-7.100.
This is a pure syntactical problem that affects newcomers to languages of the Haskell family. It won't take too long until you internalize the rule that function application has higher precedence than infix expression.
This has consequences:
Complex arguments of function application need parentheses.
In infix expressions, function applications on either side of the operator do not need parentheses (however, individual components of function application may still need them).
In Frege, in addition, the following rule holds:
The syntax of function application and infix expressions on the left hand side of a definition is identical to the one on the right hand side as far as lexemes allowed on both sides are concerned. (This holds in Haskell only when # and ~ are not used.)
This is so you can define an addition function like this:
data Number = Z | Succ Number
a + Z = a
a + Succ b = Succ a + b
Hence, when you apply this to your example, you see that syntactically, you're going to redefine the : operator. To achieve what you want, you need to write it thus:
foo bar ((baz, zab):foobar) = ....
-- ^ ^
This corresponds to the situation where you apply foo to a list you are constructing:
foo 42 (x:xs)
When you write
foo 42 x:xs
this means
(foo 42 x):xs
This has got to be a FAQ, but I can’t find it among a blizzard of questions about let vs where, so… I would like to factor an expression out of multiple top-level bindings, while scoping it only to those bindings. I can do this if I have a single binding, with a “where” clause:
foo = ... bar ... bar ...
where bar = ...
and also if I have multiple guarded equations for the same top-level binding:
foo = x | ... bar ...
| ... bar ...
where bar = ...
but there seems to be no way to have multiple top-level bindings in scope of the “where,” that is something like this:
foo = ... bar ...
baz = ... bar ...
where bar = ...
I have to define bar at the top level too. It’s not a big deal, but it would be nice to scope it more closely. Am I missing something? Thanks!
You're not missing something, it's just that a where applies only to a single expression. So with your first example, you have only one expression, in your second example the single expression is your guard, and in the third case you have two difference expressions. For reference, you can see the technical description of Haskell 98 syntax here, but the relevant part is
rhs -> = exp [where decls]
| gdrhs [where decls]
Which states that a right-hand side of a definition can consist of an expression with an optional where with declarations, or a guard right-hand side with an optional where with declarations.
If you need a binding with two functions you're going to have to define it in the same scope, that's just how it works.
There is a workaround, though. You can do something like
foo :: Int
bar :: String
(foo, bar) = (2 * baz, show baz)
where baz = 1
But I personally would prefer to see baz at the top level rather than (foo, bar) defined at the top level.
I am a huge newbie to Haskell, I actually just started 10 minutes ago. I am trying to figure out how to define a variable inside a function. Lets say I have the function
foo :: Int -> Int
foo a =
b = a * 2
b
-- Yes, I know, it doesn't do anything interesting
When I run it in GHCi I get a syntax error! How can you define a variable inside a function?
There are two ways to do this:
foo a = b where b = a * 2
foo a = let b = a * 2 in b
In most cases, the choice between them is an aesthetic rather than technical one. More precisely, where may only be attached to definitions, whereas let ... in ... may be used anywhere an expression is allowed. Both where and let introduce blocks, making multiple internal variables convenient in both cases.
Disregarding technical correctness, the answer is "sort of".
I think it's better to think of a variable as a function of zero arguments evaluating to a given value.
module Main where
import System.IO
foo :: Integer -> Integer
foo a =
b where
b = a * 2
main = do
putStrLn $ show $ foo 10
In the following code, the last phrase I can put an in in front. Will it change anything?
Another question: If I decide to put in in front of the last phrase, do I need to indent it?
I tried without indenting and hugs complains
Last generator in do {...} must be an expression
import Data.Char
groupsOf _ [] = []
groupsOf n xs =
take n xs : groupsOf n ( tail xs )
problem_8 x = maximum . map product . groupsOf 5 $ x
main = do t <- readFile "p8.log"
let digits = map digitToInt $concat $ lines t
print $ problem_8 digits
Edit
Ok, so people don't seem to understand what I'm saying. Let me rephrase:
are the following two the same, given the context above?
1.
let digits = map digitToInt $concat $ lines t
print $ problem_8 digits
2.
let digits = map digitToInt $concat $ lines t
in print $ problem_8 digits
Another question concerning the scope of bindings declared in let: I read here that:
where Clauses.
Sometimes it is convenient to scope bindings over several guarded equations, which requires a where clause:
f x y | y>z = ...
| y==z = ...
| y<z = ...
where z = x*x
Note that this cannot be done with a let expression, which only scopes over the expression which it encloses.
My question: so, the variable digits shouldn't be visible to the last print phrase. Do I miss something here?
Short answer: Use let without in in the body of a do-block, and in the part after the | in a list comprehension. Anywhere else, use let ... in ....
The keyword let is used in three ways in Haskell.
The first form is a let-expression.
let variable = expression in expression
This can be used wherever an expression is allowed, e.g.
> (let x = 2 in x*2) + 3
7
The second is a let-statement. This form is only used inside of do-notation, and does not use in.
do statements
let variable = expression
statements
The third is similar to number 2 and is used inside of list comprehensions. Again, no in.
> [(x, y) | x <- [1..3], let y = 2*x]
[(1,2),(2,4),(3,6)]
This form binds a variable which is in scope in subsequent generators and in the expression before the |.
The reason for your confusion here is that expressions (of the correct type) can be used as statements within a do-block, and let .. in .. is just an expression.
Because of the indentation rules of haskell, a line indented further than the previous one means it's a continuation of the previous line, so this
do let x = 42 in
foo
gets parsed as
do (let x = 42 in foo)
Without indentation, you get a parse error:
do (let x = 42 in)
foo
In conclusion, never use in in a list comprehension or a do-block. It is unneccesary and confusing, as those constructs already have their own form of let.
First off, why hugs? The Haskell Platform is generally the recommended way to go for newbies, which comes with GHC.
Now then, on to the letkeyword. The simplest form of this keyword is meant to always be used with in.
let {assignments} in {expression}
For example,
let two = 2; three = 3 in two * three
The {assignments} are only in scope in the corresponding {expression}. Regular layout rules apply, meaning that in must be indented at least as much as the let that it corresponds to, and any sub-expressions pertaining to the let expression must likewise be indented at least as much. This isn't actually 100% true, but is a good rule of thumb; Haskell layout rules are something you will just get used to over time as you read and write Haskell code. Just keep in mind that the amount of indentation is the main way to indicate which code pertains to what expression.
Haskell provides two convenience cases where you don't have to write in: do notation and list comprehensions (actually, monad comprehensions). The scope of the assignments for these convenience cases is predefined.
do foo
let {assignments}
bar
baz
For do notation, the {assignments} are in scope for any statements that follow, in this case, bar and baz, but not foo. It is as if we had written
do foo
let {assignments}
in do bar
baz
List comprehensions (or really, any monad comprehension) desugar into do notation, so they provide a similar facility.
[ baz | foo, let {assignments}, bar ]
The {assignments} are in scope for the expressions bar and baz, but not for foo.
where is somewhat different. If I'm not mistaken, the scope of where lines up with a particular function definition. So
someFunc x y | guard1 = blah1
| guard2 = blah2
where {assignments}
the {assignments} in this where clause have access to x and y. guard1, guard2, blah1, and blah2 all have access to the {assignments} of this where clause. As is mentioned in the tutorial you linked, this can be helpful if multiple guards reuse the same expressions.
In do notation, you can indeed use let with and without in. For it to be equivalent (in your case, I'll later show an example where you need to add a second do and thus more indentation), you need to indent it as you discovered (if you're using layout - if you use explicit braces and semicolons, they're exactly equivalent).
To understand why it's equivalent, you have to actually grok monads (at least to some degree) and look at the desugaring rules for do notation. In particular, code like this:
do let x = ...
stmts -- the rest of the do block
is translated to let x = ... in do { stmts }. In your case, stmts = print (problem_8 digits). Evaluating the whole desugared let binding results in an IO action (from print $ ...). And here, you need understanding of monads to intuitively agree that there's no difference between do notations and "regular" language elements describing a computation resulting in monadic values.
As for both why are possible: Well, let ... in ... has a broad range of applications (most of which have nothing to do with monads in particular), and a long history to boot. let without in for do notation, on the other hand, seems to be nothing but a small piece of syntactic sugar. The advantage is obvious: You can bind the results of pure (as in, not monadic) computations to a name without resorting to a pointless val <- return $ ... and without splitting up the do block in two:
do stuff
let val = ...
in do more
stuff $ using val
The reason you don't need an extra do block for what follows the let is that you only got a single line. Remember, do e is e.
Regarding your edit: digit being visible in the next line is the whole point. And there's no exception for it or anything. do notation becomes one single expression, and let works just fine in a single expression. where is only needed for things which aren't expressions.
For the sake of demonstration, I'll show the desugared version of your do block. If you aren't too familiar with monads yet (something you should change soon IMHO), ignore the >>= operator and focus on the let. Also note that indentation doesn't matter any more.
main = readFile "p8.log" >>= (\t ->
let digits = map digitToInt $ concat $ lines t
in print (problem_8 digits))
Some beginner notes about "are following two the same".
For example, add1 is a function, that add 1 to number:
add1 :: Int -> Int
add1 x =
let inc = 1
in x + inc
So, it's like add1 x = x + inc with substitution inc by 1 from let keyword.
When you try to suppress in keyword
add1 :: Int -> Int
add1 x =
let inc = 1
x + inc
you've got parse error.
From documentation:
Within do-blocks or list comprehensions
let { d1 ; ... ; dn }
without `in` serves to introduce local bindings.
Btw, there are nice explanation with many examples about what where and in keyword actually do.
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.
Haskell use (broadly speaking) exactly the same lexical scoping as most other languages.
eg.
x = 10
Results in a value referenced through x in the global scope, whereas
square x = x * x
will result in x being lexically scoped to the function square. It may help if you think of the above form being a syntactic nicety for:
square = \ x -> x * x
As to your other question i'm not sure what you mean by aliasing
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.
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
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
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!
In your example, the global definition of x is shadowed by the local definition of x. In Haskell, a variable's scope is determined by a static reading of the source code - this is called lexical scope, but can get something similar to dynamic scoping with implicit parameters (but that can lead to some unexpected behavior (I've read; never tried 'em myself)).
To sum up the other answers concisely:
lexical scope
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.
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.
Yes, Haskell has aliases. Try out this little program:
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