Why doesn't line 5 contain an indentation error. I expected to get a parse error on compilation. I expected that the + on line 5 would have to be aligned under the * in line 4.
module Learn where
x = 10
* 5
+ y -- why isn't this incorrect indentation
myResult = x * 5
y = 10
It compiles because there's no block there to consider.
Indentation only matters after where, let, do, case of.
These keywords start a block of things, and it is important to understand whether a line continues the previous entry, starts a new entry, or ends the block.
case f 5 of
A -> foo
32 -- continues the previous entry
B -> 12 -- starts a new entry
+ bar 43 -- ends the case
After = we do not need to split a block into entries: there's only a single expression. Hence no indentation rules apply.
This compiles because the definition of x was all to the right of the beginning of x. It's not important where each line starts as long as those lines are indented to the right of x.
Related
module HW2sol
where import HW2types
ins :: Eq a => a -> Bag a -> Bag a
ins x [] = [(x,1)]
ins x (y:ys) =
if x == fst y
then (x, snd y + 1) : ys
else y : (ins x ys)
HMW2types in this code is just a file that contains all of the declarations for the bag type. I have even copied and pasted other functions from online and they get the same error. This function takes an element and adds it to a bag.
[2 of 2] Compiling HW2sol ( HMW2sol.hs, HMW2sol.o )
HMW2sol.hs:5:1: parse error on input `ins'
You may be aware of Haskell's indentation rules. Anywhere you have a block of declarations (as in a let <decls> in <expr>, or a where, etc) or a block of statements (as in a do block), or a block of patterns & branches (as in a case expression) Haskell identifies the start of each entry in the block by the following logic:
Identify the column of the first character of the first entry in the block. Call this column C.
The next line that is indented less than C indicates the end of the block (and is not part of the block).
Before the end of the block, any line that is indented exactly C characters starts a new entry in the block.
Before the end of the block, any line that is indented more than C is a continuation line of the previous entry
This logic is consistently applied to all of Haskell's "block" constructs. They all have to be aligned this way1. And it turns out that the top-level declarations in a module form an aligned block! We just don't usually bother to think of them that way because they are conventionally started at column 1 (which means it isn't possible to end the block as no line can start before the first column; people normally just put all their top-level declarations at the start of the line and indent any continuations without ever thinking about "aligning the module's main block").
However, your code does not (successfully) use this conventional layout. Because you didn't insert a linebreak after the where, the first declaration begins at column 7, not column 1!
where import HW2types
^
1234567
Your type declaration of ins begins on column 1, so by rule 2 above (1 is less than 7) this indicates the end of the module's block of definitions; the compiler has to parse ins :: Eq a => ... as something that can follow the main block in the module, instead of parsing it as a declaration in the main block. That's why you get a parse error (nothing can follow the main block).
If you start your module's main block at column 7 then all of your declarations have to be indented to column 7. This actually works:
module HW2sol
where import HW2types
ins :: Eq a => a -> Bag a -> Bag a
ins x [] = [(x,1)]
ins x (y:ys) =
if x == fst y
then (x, snd y + 1) : ys
else y : (ins x ys)
However you'll probably find it much easier to simply put a line break after the where and have import HW2types on a new line.
1 Alternatively, blocks and their entries can be explicitly delimited with braces and semicolons. But this is not usual style in Haskell.
i am new to haskell and i am trying to make the following code work:
abc :: fooType
abc = do
let loop c d = do
let q = borrow "a"
d2 = d + q
c2 = c + 1
if c2 == 10
then
if d2 >= 60
then
maybeB <- cast "b"
return $ isJust maybeB
else
return $ False
else
loop c2 d2
loop 0 0
i keep getting:
error: parse error on input `let'
let q = borrow "a"
the code looks correct to me, would that be a problem with indentation? I know do blocks have some specific rules on how to set up indentation but from what i've been reading it looks correct.., can anyone spot what the problem is?
ps: borrow returns Int > 0,
cast returns maybe int. But the compilation is failing on line2
let and do are both block heralds -- that means that the start of the next lexical token starts a block and sets the indentation level of that block. Additionally, indentation must increase to nest blocks. So:
abc = do -- block herald
-- "let" is the next token after a block herald, so it sets an indentation level;
-- it is also itself a block herald
-- "loop" is the next token after a block herald, so it sets an indentation level
-- "do" is a block herald
let loop = do
-- "let" is the next token after a block herald, so it sets an indentation level,
-- **and must be deeper than the enclosing indentation;**
-- it is also a block herald
-- "q" is the next token after a block herald, so it sets an indentation level
let q = ...
-- "d2" must use the indentation level of the block it wants to be in;
-- presumably the enclosing "let"
d2 = ...
c2 = ...
-- this "if" must use the indentation of the block it wants to be in;
-- presumably the closest enclosing "do" block
if ...
-- this "then" can be indented the same as the "if" above it, but I find
-- that confusing; my preferred style indicates the nesting structure
then ...
else ...
-- this "loop" must use the indentation of the block it wants to be in; presumably the outermost "do" block
loop
There's a lot going on in the second line, so it's easy to lose track of all the things you need to think about. Anyway, the main mistake in your code is that loop sets an indentation level, and the let shortly after it must be indented more than it.
Is it possible to reassign the same variable in ghci ? Of course this isn't possible in normal Haskell (at least without something like an IORef), but I was curious because the it variable in ghci that you get by enabling the :m option. With that enabled I get an experience where it is effectively reassignable by not binding the next expression to anything, e.g.
λ> 1 + 1
2
it :: Num a => a
λ> it
2
it :: Num a => a
λ> it + 1
3
it :: Num a => a
λ> it
3
it :: Num a => a
Is there a way to realize the same effect for an arbitrary named variable, not just the special it ?
Each new line in GHCi enters new, nested scope. Consider
> x = 1
> x
1
> foo y = x + y
> foo 41
42
> x = 7 -- new x
> x
7
> bar y = x + y -- refers to new x
> bar 41
48
> foo 41 -- still refers to the same old x binding
42
Second binding of x defines new same-named variable.
Naturally, it shadows the previous binding for that name, making it inaccessible in itself. Any other entity (like foo) which referenced it before though, will continue to hold that reference, no matter the shadowing for the newer, nested environments.
This follows the principle of immutability of values in Haskell: the foo remains the same.
One caveat:
> :{
x = 1
foo y = x + y
x = 7 -- error: conflicting definition
bar y = x + y
:}
causes an error, because lines entered in multiline mode belong to the same scope.
In other words the answer to your question is no, it would break the fundamental purity properties of Haskell.
it is not reassigned either, it is defined anew in each new nested environment, whenever there is any output, being bound to the output value:
> x
7
> it
7
> it_2 -- made a typo
error: Not in scope: `it_2'
> it+2 -- no previous output, same `it` in effect
9
> it+2 -- most recent `it` is 9
11
So you can always shadow your variable and create a new binding with the same name, but you can't change the old binding, because it is a part of history now, and the past can not be changed, by definition. It already happened.
Or you could create your own Haskell interpreter where you'd give a user an ability to "change" an old binding, but what would really happen is that a new copy of the interpreter would be spawned even "playing" all the recorded user actions at the prompt -- new definitions and all -- from that point on. Then the user would end up with a changed copy which would be oblivious to the existence of the first one. You could even kill the original at that point. Could this be considered as user having changed the past? The user's past hasn't changed, their time goes forward. The new copy's past was always what it is now, as far as it is concerned. The older original (copy?) is gone... A question to ponder.
I am doing some haskell exercises to learn the language and I have a syntax error I was hoping someone could help me with:
-- Split a list l at element k into a tuple: The first part up to and including k, the second part after k
-- For example "splitAtIndex 3 [1,1,1,2,2,2]" returns ([1,1,1],[2,2,2])
splitAtIndex k l = ([l !! x | x <- firstHalfIndexes], [l !! x | x <- firstHalfIndexes])
where firstHalfIndexes = [0..k-1]
secondHalfIndexes = [k..(length l-1)]
The syntax error is "parse error on input ‘=’" and seems to be coming from my second where clause, but I can't work out why the first where clause is ok but not the second?
The Haskell Report specifies that tab characters flesh out text to the next multiple of eight. Your code appears to assume that it gets fleshed out to the next multiple of four. (My best guess. Might also be configured to be five or six, but those settings seem less popular than four.)
See my page on tabs for ideas on how to safely use tabs in Haskell code; or else do what most other folks do and configure your editor to expand tabs to spaces.
For an example of the style I use, your current code looks like this to the compiler (using > to mark tabs and _ for spaces):
splitAtIndex_..._=_...
> where_> firstHalfIndexes_=_...
> > > secondHalfIndexes_=_...
I would write it to look like this to the compiler:
splitAtIndex_..._=_...
> where_> firstHalfIndexes_=_...
> ______> secondHalfIndexes_=_...
This also looks correct with four-space tabstops (and indeed any size tabstop):
splitAtIndex_..._=_...
> where_> firstHalfIndexes_=_...
> ______> secondHalfIndexes_=_...
(Actually, I would probably just use one space after where rather than a space and a tab, but that's an aesthetics thing, not really a technical one.)
Search for "vim haskell indent" on SO. There are lot of answers for how to configure Vim for Haskell indentation. None of them really "work". They don't provide code as is recommended by the Haskell indentation wiki page. For example, alignment of statements in a do or let block, the = and | of a data type, etc.
Does a Vim solution exist that generates code like the wiki?
This might not be the answer your are looking for, but there is a way you can follow the indentation wiki guide and be compatible with most editors.
For example, do-blocks
Instead of
myFunc x = do y <- bar
return $ x + y
You can indent it like this
myFunx x = do
y <- bar
return $ x + y
This is explicitly mentioned as an acceptable alternative in the indentation wiki.
In the same way, you can format data types
data FooBar
= Foo
| Bar
| Asdf
Guards
myFunc x
| x < 0 = 0
| otherwise = x
Where-clauses
myFunc x = x + y + c where
y = x + 5
c = x * y
And so on...
I personally started to use this kind of style because, like you said, no editor could reliable indent the code otherwise. This works better in all editors, as the indentation is always a multiple of four (or whatever else you pick for your base indentation level). As I used this style, I also started to prefer this consistent indentation level visually, so I wouldn't go back at this point even if editors got smarter.