I am totally newbie to haskell.
I have such snippet code
lucky:: Int->String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry , youre out of luck pal!"
I tried to input to terminal directly, seems not right.
But if I want to put this in file and load this file, then call lucky function. How should I construct this file?
Thank you!
I tried this:
module Main where
lucky:: Int->String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry , youre out of luck pal!"
main = do
But when i try to call lucky in terminal, i got this:
factorial.hs:7:8: Empty 'do' construct
lucky 7
<interactive>:1:1: Not in scope: `lucky'
The problem is that your last line, main = do, is a syntax error; if your file has a syntax error then none of the functions in it will load. It should work fine if you take out your definition of main and try to load it.
On an unrelated note, generally Haskell type signatures are written with spacing like lucky :: Int -> String.
You don't need the module Main where or main = do lines.
You can load and use function definitions into ghci, simply by saving the file with a ".hs" extension, then typing :load and the the filename
Related
For instance:
let x = 1 in putStrLn [dump|x, x+1|]
would print something like
x=1, (x+1)=2
And even if there isn't anything like this currently, would it be possible to write something similar?
TL;DR There is this package which contains a complete solution.
install it via cabal install dump
and/or
read the source code
Example usage:
{-# LANGUAGE QuasiQuotes #-}
import Debug.Dump
main = print [d|a, a+1, map (+a) [1..3]|]
where a = 2
which prints:
(a) = 2 (a+1) = 3 (map (+a) [1..3]) = [3,4,5]
by turnint this String
"a, a+1, map (+a) [1..3]"
into this expression
( "(a) = " ++ show (a) ++ "\t " ++
"(a+1) = " ++ show (a + 1) ++ "\t " ++
"(map (+a) [1..3]) = " ++ show (map (+ a) [1 .. 3])
)
Background
Basically, I found that there are two ways to solve this problem:
Exp -> String The bottleneck here is pretty-printing haskell source code from Exp and cumbersome syntax upon usage.
String -> Exp The bottleneck here is parsing haskell to Exp.
Exp -> String
I started out with what #kqr put together, and tried to write a parser to turn this
["GHC.Classes.not x_1627412787 = False","x_1627412787 = True","x_1627412787 GHC.Classes.== GHC.Types.True = True"]
into this
["not x = False","x = True","x == True = True"]
But after trying for a day, my parsec-debugging-skills have proven insufficient to date, so instead I went with a simple regular expression:
simplify :: String -> String
simplify s = subRegex (mkRegex "_[0-9]+|([a-zA-Z]+\\.)+") s ""
For most cases, the output is greatly improved.
However, I suspect this to likely mistakenly remove things it shouldn't.
For example:
$(dump [|(elem 'a' "a.b.c", True)|])
Would likely return:
["elem 'a' \"c\" = True","True = True"]
But this could be solved with proper parsing.
Here is the version that works with the regex-aided simplification: https://github.com/Wizek/kqr-stackoverflow/blob/master/Th.hs
Here is a list of downsides / unresolved issues I've found with the Exp -> String solution:
As far as I know, not using Quasi Quotation requires cumbersome syntax upon usage, like: $(d [|(a, b)|]) -- as opposed to the more succinct [d|a, b|]. If you know a way to simplify this, please do tell!
As far as I know, [||] needs to contain fully valid Haskell, which pretty much necessitates the use of a tuple inside further exacerbating the syntactic situation. There is some upside to this too, however: at least we don't need to scratch our had where to split the expressions since GHC does that for us.
For some reason, the tuple only seemed to accept Booleans. Weird, I suspect this should be possible to fix somehow.
Pretty pretty-printing Exp is not very straight-forward. A more complete solution does require a parser after all.
Printing an AST scrubs the original formatting for a more uniform looks. I hoped to preserve the expressions letter-by-letter in the output.
The deal-breaker was the syntactic over-head. I knew I could get to a simpler solution like [d|a, a+1|] because I have seen that API provided in other packages. I was trying to remember where I saw that syntax. What is the name...?
String -> Exp
Quasi Quotation is the name, I remember!
I remembered seeing packages with heredocs and interpolated strings, like:
string = [qq|The quick {"brown"} $f {"jumps " ++ o} the $num ...|]
where f = "fox"; o = "over"; num = 3
Which, as far as I knew, during compile-time, turns into
string = "The quick " ++ "brown" ++ " " ++ $f ++ "jumps " ++ o ++ " the" ++ show num ++ " ..."
where f = "fox"; o = "over"; num = 3
And I thought to myself: if they can do it, I should be able to do it too!
A bit of digging in their source code revealed the QuasiQuoter type.
data QuasiQuoter = QuasiQuoter {quoteExp :: String -> Q Exp}
Bingo, this is what I want! Give me the source code as string! Ideally, I wouldn't mind returning string either, but maybe this will work. At this point I still know quite little about Q Exp.
After all, in theory, I would just need to split the string on commas, map over it, duplicate the elements so that first part stays string and the second part becomes Haskell source code, which is passed to show.
Turning this:
[d|a+1|]
into this:
"a+1" ++ " = " ++ show (a+1)
Sounds easy, right?
Well, it turns out that even though GHC most obviously is capable to parse haskell source code, it doesn't expose that function. Or not in any way we know of.
I find it strange that we need a third-party package (which thankfully there is at least one called haskell-src-meta) to parse haskell source code for meta programming. Looks to me such an obvious duplication of logic, and potential source of mismatch -- resulting in bugs.
Reluctantly, I started looking into it. After all, if it is good enough for the interpolated-string folks (those packaged did rely on haskell-src-meta) then maybe it will work okay for me too for the time being.
And alas, it does contain the desired function:
Language.Haskell.Meta.Parse.parseExp :: String -> Either String Exp
Language.Haskell.Meta.Parse
From this point it was rather straightforward, except for splitting on commas.
Right now, I do a very simple split on all commas, but that doesn't account for this case:
[d|(1, 2), 3|]
Which fails unfortunatelly. To handle this, I begun writing a parsec parser (again) which turned out to be more difficult than anticipated (again). At this point, I am open to suggestions. Maybe you know of a simple parser that handles the different edge-cases? If so, tell me in a comment, please! I plan on resolving this issue with or without parsec.
But for the most use-cases: it works.
Update at 2015-06-20
Version 0.2.1 and later correctly parses expressions even if they contain commas inside them. Meaning [d|(1, 2), 3|] and similar expressions are now supported.
You can
install it via cabal install dump
and/or
read the source code
Conclusion
During the last week I've learnt quite a bit of Template Haskell and QuasiQuotation, cabal sandboxes, publishing a package to hackage, building haddock docs and publishing them, and some things about Haskell too.
It's been fun.
And perhaps most importantly, I now am able to use this tool for debugging and development, the absence of which has been bugging me for some time. Peace at last.
Thank you #kqr, your engagement with my original question and attempt at solving it gave me enough spark and motivation to continue writing up a full solution.
I've actually almost solved the problem now. Not exactly what you imagined, but fairly close. Maybe someone else can use this as a basis for a better version. Either way, with
{-# LANGUAGE TemplateHaskell, LambdaCase #-}
import Language.Haskell.TH
dump :: ExpQ -> ExpQ
dump tuple =
listE . map dumpExpr . getElems =<< tuple
where
getElems = \case { TupE xs -> xs; _ -> error "not a tuple in splice!" }
dumpExpr exp = [| $(litE (stringL (pprint exp))) ++ " = " ++ show $(return exp)|]
you get the ability to do something like
λ> let x = True
λ> print $(dump [|(not x, x, x == True)|])
["GHC.Classes.not x_1627412787 = False","x_1627412787 = True","x_1627412787 GHC.Classes.== GHC.Types.True = True"]
which is almost what you wanted. As you see, it's a problem that the pprint function includes module prefixes and such, which makes the result... less than ideally readable. I don't yet know of a fix for that, but other than that I think it is fairly usable.
It's a bit syntactically heavy, but that is because it's using the regular [| quote syntax in Haskell. If one wanted to write their own quasiquoter, as you suggest, I'm pretty sure one would also have to re-implement parsing Haskell, which would suck a bit.
Why is the function name repeated in
example:
lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"
when should I not be repeating function name? what is the meaning of it?
thanks
What you are seeing is pattern match in action.
I will show you another example:
test 1 = "one"
test 2 = "two"
test 3 = "three"
Demo in ghci:
ghci> test 1
"one"
ghci> test 2
"two"
ghci> test 3
"three"
ghci> test 4
"*** Exception: Non-exhaustive patterns in function test
So, when you call any function, the runtime system will try to match
the input with the defined function. So a call to test 3 will
initially check test 1 and since 1 is not equal to 3, it will
move on to the next definition. Again since 2 is not equal to 3,
it will move to the next defintion. In the next definiton since 3 is
equal to 3 it will return "three" String back. When you try to
pattern match something, which doesn't exist at all, the program
throws the exception.
This kind of pattern matching can be transformed to a case statement (and indeed, that's what compilers will normally do!):
lucky' n = case n of
7 -> "LUCKY NUMBER SEVEN!"
x -> "Sorry, you're out of luck, pal!"
Because the x isn't really used, you'd normally write _ -> "Sorry, ..." instead.
Note that this is not2 the same as
lucky'' n = if n==7 then ...
Equality comparison with (==) is in general more expensive1 than pattern matching, and also comes out uglier.
1 Why it's more expensive: suppose we have a big data structure. To determine that they are equal, the program will need to dig through both entire structures, make sure really all branches are equal. However, if you pattern match, you will just compare a small part you're interested in right now.
2 Actually, it is the same in the case, but just because the compiler has a particular trick for pattern matching on numbers: it rewrites it with (==). This is really special for Num types and not true for anything else. (Except if you use the OverloadedStrings extension.)
That definition of lucky uses "pattern matching", and equals (in this case)
lucky :: (Integral a) => a -> String
lucky a = if a == 7
then "LUCKY NUMBER SEVEN!"
else "Sorry, you're out of luck, pal!"
I assume you're looking at learn you a haskell. After that example, it says that
When you call lucky, the patterns will be checked from top to bottom and when it conforms to a pattern, the corresponding function body will be used.
So the first line indicates the type of the function, and later lines are patterns to check. Each line has the function name so the compiler knows you're still talking about the same function.
Think of it this way: When you write the expression lucky (a+b) or whatever, the compiler will attempt to replace lucky (a+b) with the first thing before the = in the function definition that "fits." So if a=3 and b=4, you get this series of replacements:
lucky (a+b) =
lucky (3+4) =
--pattern matching occurs...
lucky 7 =
"LUCKY NUMBER SEVEN!"
This is part of what makes Haskell so easy to reason about in practice; you get a system that works similarly to math.
I have this error sometimes, though not all of the time, and it's driving me crazy. I don't know if it's a bug or if there is some behaviour or fix that I am not aware of.
I am entering a multiple-line command using :{ and :}, and SOMETIMES when I want to conclude the command, like below, I receive the error as shown below:
*MyModule| :}
unknown command ':}'
use :? for help.
I'd say it works properly 97 percent of the time, but 3 percent of the time I get this situation.
As far as I know, it should always work to type :} to close the multiple line entry, as described here:
http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/interactive-evaluation.html
At the moment, the only way that I know to escape this situation when it happens is ctrl+D, which kills ghci unfortunately.
A. Is this a bug or is there some reason that :} would suddenly become an "unknown command"?
B. If I get to this situation, is there a way to recover without using ctrl+D? It doesn't matter how many times I try :}, it always results in "unknown command" once I have entered this situtation, though what I expect is for this command to close the multiple line entry.
Like it says in the question, this is GHCi, version 7.6.3, on Arch Linux.
As I already noted in the comments, the reason for this behaviour is the GHCi doesn't properly reset the prompt when Ctrl-C is pressed. The source of the problem probably lies in the following code (Taken from ghci-ng):
multiLineCmd q = do
st <- lift getGHCiState
let p = prompt st
lift $ setGHCiState st{ prompt = prompt2 st }
mb_cmd <- collectCommand q ""
lift $ getGHCiState >>= \st' -> setGHCiState st'{ prompt = p }
return mb_cmd
(See InteractiveUI.hs line 712)
If collectCommand throws UserInterrupt, then the line that resets the promt will never be executed. I changed this code to:
multiLineCmd q = do
st <- lift getGHCiState
let p = prompt st
lift $ setGHCiState st{ prompt = prompt2 st }
mb_cmd <- collectCommand q "" `GHC.gfinally` lift (getGHCiState >>= \st' -> setGHCiState st'{ prompt = p })
return mb_cmd
Which fixes the problem.
This is a known bug. Everything is working fine except that ghci sometimes keeps printing the multiline prompt when it should be printing the normal prompt.
For example;
data TRAINING=AGAIN Int [TRAINING]
|RUN
|JUMP
|PUNCH Int
deriving (Eq,Show,Read)
is defined and I want that if the User enters something like:
"RUN, PUNCH 15, AGAIN 3 [JUMP, AGAIN 2 [PUNCH 20]]"
then the program should return
[RUN,PUNCH 15,AGAIN 3 [JUMP,AGAIN 2 [PUNCH 20]]]
So I wrote
fight :: String->[TRAINING]
fight xs=[read xs ::TRAINING]
but I am getting "no parse Exception". I am novice and I want to know what a "no parse Exception" is and how I can fix it ?
A no parse exception means that what you gave Haskell isn't the correct pattern for the instance of Read. In this case it's because list's are shown like this:
[<show element>,<show element>...]
And you're missing the outer brackets. Fixing it is as easy as seeing what the output should be:
Prelude> show [RUN,PUNCH 15,AGAIN 3 [JUMP,AGAIN 2 [PUNCH 20]]]
"[RUN,PUNCH 15,AGAIN 3 [JUMP,AGAIN 2 [PUNCH 20]]]"
So you need to surround the whole thing with []'s. Your function is right, you just have a slightly incorrect input string.
If you don't like this restriction, it may be time to just write a simple parser with Parsec or similar. Though this might be a bit challenging if you're totally new to Haskell.
In other words, following jozefg's answer:
fight xs = read xs ::[TRAINING]
and also:
"[RUN, PUNCH 15, AGAIN 3 [JUMP, AGAIN 2 [PUNCH 20]]]"
I've decided to teach myself Haskell and I have never been so frustrated in all my life. I am going through the tutorial at http://lisperati.com/haskell/ which is the easiest one I could find. All that I am trying to do is read a text file called people.txt which contains a list of numbers and print the length of the list. This code is straight from the tutorial.
import Data.List
type Person = [Int]
main = do
people_text <- readFile "people.txt"
let people :: [Person]
people = read people_text
putStr "Number of people "
putStr (length people_text)
When I try to run the file with runHaskell tutorial03.hs I get this error message
tutorial03.hs:9:13:
Illegal signature in pattern: [Person] people
Use -XScopedTypeVariables to permit it
Using the XScopedTypeVariables flag I get
tutorial03.hs:10:17: Not in scope: type variable `people'
Could someone please explain what I am doing wrong.
Luqui's right that indentation is the issue. The compiler is treating your definition as if it were
let people :: [Person] people = read people_text
which does indeed look like you're writing a type signature in a pattern (and using people both as the function name and a pattern variable, to boot -- peculiar but permitted!).
Crucially, let is a layout keyword, introducing a block of lines which should all be indented to the same horizontal position. By following the signature with a more-indented line, you indicate that you're contuing the line with the signature, rather than starting a new line for the actual definition. If you don't like this fussy layout convention, you can use noisy semicolons.
If you want your definition to be treated as two lines, you either need to be careful to line up the peoples vertically...
let people :: [Person]
people = read people_text
or to signal the line ending explicitly with a semicolon.
let people :: [Person] ;
people = read people_text
The former would be preferable, although I expect most Haskellers would just supply a type annotation for read people_text rather than a signature for the definition, like this:
let people = read people_text :: [Person]
Once you've fixed that, you'll need to contend with the fact that the length of the list is a number, but putStr outputs strings. The print command may be more useful for this purpose.
change it to this, works for me:
...
let people :: [Person]
people = read people_text
...
print (length people_text)