I tried various combinations to fix the indentation for the following code but failed. How shall i fix the below
fold' list = do
let result = foldl (+) list
in putStrLn $ "Reduced " ++ show(result)
return $ result
parse error on input `in'
Failed, modules loaded: none.
In a do clause, the in keyword should not be used.
So you can fix it with writing:
fold' list = do
let result = foldl (+) list
putStrLn $ "Reduced " ++ show(result) -- no "in" keyword
return $ result
The scope of the let statement is the rest of the clauses.
The translation is like specified in section 3.14 of the Haskell report [link]:
do {e} = e
do {e;stmts} = e >> do {stmts}
do {p <- e; stmts} = let ok p = do {stmts}
ok _ = fail "..."
in e >>= ok
do {let decls; stmts} = let decls in do {stmts}
So in case we define two let statements with the same name (which is not recommended), the first one moving to the top will count.
So for:
foo = do
let x = "4"
putStrLn x
let x = "2"
putStrLn x
It will translate into:
foo = let x = "4" in (putStrLn x >> (let x = "2" in putStrLn x))
So the first putStrLn will use the x defined by let x = "4" whereas the last one will use the x defined in let x = "2".
Related
Can't get my haskell program to work
sort [] = []
sort (x:xs) = sort [a | a <- xs , a<=x ] ++ [x] ++ sort [a | a <- xs , a > x]
getList:: Int->[IO Int]
getList 0 = [] --declaring the empty list
getList n = [a | a <- [getNumber] ] ++ getList (n-1)
getNumber::IO Int --get number function
getNumber = do
s <- getLine
return (read s)
--Main function to handle
main = do
p <- getNumber -- taking the number of variable
lst <- sequence (getList p) --calling gtlistFunction to input the list
print (sort lst) --print
Error:
quicksort.hs:13:6: error:
parse error on input `='
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
|
13 | main = do
| ^
You must indent all do-blocks:
-- NOT correct: this will fail
main = do
putStrLn "This is..."
putStrLn "WRONG!"
-- Correct:
main = do
putStrLn "This is..."
putStrLn "correct!"
The number of spaces doesn't matter as long it is consistent.
To avoid this you could use c-like notation:
-- Also correct:
main = do {
putStrLn "This is...";
putStrLn "also correct!";
}
And this leaves you free to indent as you like. Example:
-- Also correct:
main = do
{ putStrLn "This is..."
; putStrLn "also correct!"
;}
Without indentation, the parser doesn't know that main = ... starts a new definition, separate from the preceding definition of getNumber. The following would work fine:
getNumber::IO Int
getNumber = do
s <- getLine
return (read s)
main = do
p <- getNumber
lst <- sequence (getList p)
print (sort lst)
The transition from one-space indentation to no indentation is enough to tell the parser that return (read s) is the last line of the do block defining getNumber, and that main = do is the beginning of a new top-level definition.
Either indenting your code, or using the explicit brace syntax in AJFarmar's answer, lets the parser know where one definition ends and the next begins.
I'm a newbie in Haskell and I'm reading "Learn You a Haskell for Great Good!".
An expression that defines with a "name" and a "space", followed by "parameters" could be used as functions.
Consider the following code:
doubleMe = 2
this code actually follows the rule above, so we could see it as a function. but it really seems like an assign operations in java or c++.
So, How to understand the variable in Haskell?
At the top level of a program, name = expression is a definition. It creates a variable, in the sense of a mathematical variable—just a name for some expression. It can be a definition of a value:
two :: Int
two = 2
Or a definition of a function:
twice :: Int -> Int
twice x = x * two
A definition refers to a function if its type has a function arrow ->.
In a do block or GHCi, let name = expression is a local definition.
main :: IO ()
main = do
let greet name = "Hello, " ++ name ++ "!"
putStrLn (greet "world")
Finally, there is another use of the let keyword: let name = expression1 in expression2. This creates a variable local to a single expression:
length (let x = "hello" in x ++ x) == 10
Be aware that let takes a block of bindings, so it’s subject to the layout rules like other layout keywords, such as do, where, of as in case…of, and so on:
main :: IO ()
main = do
-- Bindings must be aligned past the start column.
-- ↓
let greeting name = "Hello, " ++ name ++ "!"
parting name = "Goodbye, " ++ name ++ "!"
putStrLn (greeting "world")
putStrLn (parting "world")
length $ let x = "hello"
y = "goodbye"
in x ++ y
As with other layout keywords, can instead put a newline and a fixed amount of indentation after let, and then not worry about alignment:
main = do -- ← newline+indent
let -- ← newline+indent
greeting name = …
parting name = …
…
length $ let
x = "hello"
y = "goodbye"
in x ++ y
Or you can always include explicit curly braces and semicolons:
main :: IO ();
main = do {
let {
greeting name = "Hello, " ++ name ++ "!";
parting name = "Goodbye, " ++ name ++ "!";
};
putStrLn (greeting "world");
putStrLn (parting "world");
};
length $ let {
x = "hello";
y = "goodbye";
} in x ++ y
I am currently working 99 haskell problems
I cannot understand why am I getting an error in this function :-
repli :: [a] -> Int -> [a]
repli xs n = concatMap (take n . repeat) xs
If you are using the REPL, try
>>> let repli xs n = concatMap (take n . repeat) xs
Writing Haskell in the REPL (ake GHCi) is a bit different to writing it in a file. For one thing, variable bindings and function definitions have to be prefixed with let as in
>>> let a = 1
>>> let f x = x + a
For another, you generally have to enter definitions all on one line. You can separate separate definitions with a semicolon, like this
>>> let a = 1; b = 2
or you can use multi-line mode, like this
>>> :{
>>> let c = 3
>>> d = 4
>>> :}
If you've learnt about monads (have you?) then you can imagine that everything you write in the REPL is part of a do block which is of type IO (), with the statements executed as you type them. So in a file you might write
main :: IO ()
main = do
name <- getLine
let greeting = "Hello " ++ name ++ "!"
putStrLn greeting
whereas in the REPL you would write
>>> name <- getLine
Chris
>>> let greeting = "Hello " ++ name ++ "!"
>>> putStrLn greeting
Hello Chris!
>>>
import Data.ByteString as B
import Data.ByteString.Internal as I
import Data.Bits
main = do input <- getLine
let bs = B.pack input
let intermediatebs = unfoldrN ((B.length bs)*2) unfld 0
where unfld i
|Prelude.rem i 2 == 0 = Just (top4 $ B.index bs (i/2) , i+1)
|otherwise = Just (bottom4 $ B.index bs (i/2) , i+1)
top4bits x = shiftR x 4
bottom4bits x = x .&. 0x0F
top4 x = convertASCIIword8 $ top4bits x
bottom4 x = convertASCIIword8 $ bottom4bits x
convertASCIIword8 x
|x <= 9 = I.c2w '0' + x
|otherwise = I.c2w 'A' + (x-10)
let outputbs = B.map I.w2c $ intermediatebs
in do putStrLn (outputbs)
i am getting this compilation error
The last statement in a 'do' construct must be an expression:
let intermediatebs = unfoldrN ((B.length bs) * 2) unfld 0
It's hard to see exactly what you want here. It is possible to make your code parse with only indentation changes:
import Data.ByteString as B
import Data.ByteString.Internal as I
import Data.Bits
main = do
input <- getLine
let bs = B.pack input
let intermediatebs = unfoldrN ((B.length bs)*2) unfld 0
where
unfld i
| Prelude.rem i 2 == 0 = Just (top4 $ B.index bs (i/2) , i+1)
| otherwise = Just (bottom4 $ B.index bs (i/2) , i+1)
top4bits x = shiftR x 4
bottom4bits x = x .&. 0x0F
top4 x = convertASCIIword8 $ top4bits x
bottom4 x = convertASCIIword8 $ bottom4bits x
convertASCIIword8 x
| x <= 9 = I.c2w '0' + x
| otherwise = I.c2w 'A' + (x-10)
let outputbs = B.map I.w2c $ intermediatebs
putStrLn (outputbs)
although it won't compile due to ambiguous getLine and putStrLn occurrences. You may want to import qualified where appropriate. Key observations:
Do-blocks, let-blocks etc. start from the left edge of the first thing inside them, regardless of where the keyword is itself. E.g.
do x
y
-- ^ because of where the x is, all future lines have to line up with it
let x = ...
y = ...
-- ^ if you have code appearing left of here, the let-block ends
As a consequence, I often give do and where their own line before starting a block. In the example I gave above, you can see that even if I moved the do-block into a function with a longer or shorter name, the indentation wouldn't change.
Lines in the same block that start indented are a continuation of the previous line. Guards are a continuation so need to be indented, likewise where for a let assignment needs to be indented further than the assignment itself.
The in do at the end of your block was redundant, so I removed it (alternatively, just indenting it would have worked too).
The error message is not caused by an indentation error so much as an ordering error. You seem to have inserted the where-block in the middle of your do-block. That does not work. The entire do-block, including the final expression, should come before the where block.
That said, you do have indentation error in your definitions inside your where-block: you need to indent the pattern guards.
Your outer do consists only of input <- getLine since the following token let is already less indended than input (which makes no sense anyway, but ....)
Perhaps you mean:
do input <- getLine
let ....
let ..... where
unfld ....
But one can only guess. Use indendation to make clear what items belong together, and what items are subitems of others. The style above rather obscures this. Also, you shouldn't write
foo x y z
| ..... =
because the compiler would see
foo x y z; | ... =
I'm a newbie in Haskell and I'd like some opinions about improving this script. This is a code generator and requires a command line argument to generate the sql script.
./GenCode "people name:string age:integer"
Code:
import Data.List
import System.Environment (getArgs)
create_table :: String -> String
create_table str = "CREATE TABLE " ++ h (words str)
where h (x:xs) = let cab = x
final = xs
in x ++ "( " ++ create_fields xs ++ ")"
create_fields (x:xs) = takeWhile (/=':') x ++ type x ++ sig
where sig | length xs > 0 = "," ++ create_fields xs
| otherwise = " " ++ create_fields xs
create_fields [] = ""
type x | isInfixOf "string" x = " CHARACTER VARYING"
| isInfixOf "integer" x = " INTEGER"
| isInfixOf "date" x = " DATE"
| isInfixOf "serial" x = " SERIAL"
| otherwise = ""
main = mainWith
where mainWith = do
args <- getArgs
case args of
[] -> putStrLn $ "You need one argument"
(x:xs) -> putStrLn $ (create_table x)
I think you understand how to write functional code already. Here are some small style notes:
Haskell usually uses camelCase, not under_score_separation
In create_table, cabo and final are not used.
Usually a list-recursive function like create_fields puts the empty list case first.
I would not make create_fields recursive anyway. The comma-joining code is quite complicated and should be separated from the typing code. Instead do something like Data.List.intercalate "," (map create_field xs). Then create_field x can just be takeWhile (/=':') x ++ type x
Especially if there are a lot of types to be translated, you might put them into a map
Like so:
types = Data.Map.fromList [("string", "CHARACTER VARYING")
,("integer", "INTEGER")
-- etc
]
Then type can be Data.Maybe.fromMaybe "" (Data.Map.lookup x types)
Code can appear in any order, so it's nice to have main up front. (This is personal preference though)
You don't need mainWith.
Just say
main = do
args <- getArgs
case args of
[] -> ...
You don't need the dollar for the calls to putStrLn. In the first call, the argument wouldn't require parentheses anyway, and in the second, you supply the parentheses. Alternatively, you could keep the second dollar and drop the parentheses.
Don't use length xs > 0 (in sig); it needlessly counts the length of xs when all you really wanted to know is whether it's empty. Use null xs to check for a non-empty list:
...
where sig | null xs = ... -- Empty case
| otherwise = ... -- Non-empty case
or add an argument to sig and pattern match:
...
where sig (y:ys) = ...
sig [] = ...
Although Nathan Sanders' advice to replace the whole recursive thing with intercalate is excellent and makes this a moot point.
You're also identifying the type by passing the whole "var:type" string into type, so it is testing
"string" `isInfixOf` "name:string"
etc.
You could use break or span instead of takeWhile to separate the name and type earlier:
create_fields (x:xs) = xname ++ type xtype ++ sig
where
(xname, _:xtype) = break (==':') x
sig = ...
and then type can compare for string equality, or look up values using a Map.
A quick explanation of that use of break:
break (==':') "name:string" == ("name", ":string")
Then when binding
(xname, _:xtype) to ("name", ":string"),
xname -> "name"
_ -> ':' (discarded)
xtype -> "string"