I have been reading "learn you haskell for great good", and in this part:
"let’s put a string that represents a person in a script and then load that script in GHCi:
mysteryDude = "Person { firstName =\"Michael\"" ++
", lastName =\"Diamond\"" ++
", age = 43}"
We wrote our string across several lines like this for increased readability. If we want to read that string, we need to tell Haskell which type we expect in return:
ghci> read mysteryDude :: Person
But I don't know how to create the 'script', it's in mysteryDude.hs file, and then I need to load it with >:l mysteryDude.hs
Or what. But I tried it and I got this error:
*Main> read mysteryDude.hs :: Person
<interactive>:50:23: error:
Not in scope: type constructor or class ‘Person’
*Main> read mysterDude.hs :: Person
I see that in the web here, they change it, and don't do it in the same way, so, maybe it's an error.
But even if in this example is an error I would like to know how to write a 'script' and load data from it.
From comments I deduced the problem. :l in ghci forgets all previous :ls and all definitions that you made in REPL. You should either:
Make files import each other (avoiding import cycles). Filenames and module names must match.
import both files in ghci. Again, module names should match the names of files.
Make all your definitions in REPL's toplevel. You may use multiline snippets surrounding them by :{ :}. Not recommended tho
Related
I have a string containing words separated by spaces. I would like to get the individual words.
I verified (in ghci) that the following solution works well:
import Data.String
list_of_words = words "a b c"
but I happened to stumble accross the splitOn function, and since I am still in the basement of Haskell programming, and a curious mind, I wondered whether I could also achieve my goal using this function. Hence I tried:
import Data.List
lw = Data.List.splitOn "a b c"
only to get the error message
Not in scope: ‘Data.List.splitOn’
No module named ‘Data.List’ is imported
I don't understand the first message, but the second one is ridiculous, since I imported the module, and the module name is shown in the ghci prompt. Then I realized that the website above referst to a module Data.List.Split, not Data.List. Hence I tried
import Data.List.Split
only to get the error messages
Could not find module ‘Data.List.Split’
Well, curiosity killed the cat. I should have stayed with my original words solution. But since I opened the box now, could some kind soul explain to me, why my attempts have failed, and how I could have it done correctly?
UPDATE Following the comments to my question, I tried
splitOn " " "a c d"
but this time get the error message
Variable not in scope: splitOn :: [Char] -> [Char] -> t
Perhaps you meant one of these:
‘Text.splitOn’ (imported from Data.Text),
‘splitAt’ (imported from Data.List),
‘Text.splitAt’ (imported from Data.Text)
It looks like Data.Text (which I happened to import too) also has a splitOn function with different signature. Hence, I started a fresh ghci without any imports, and just did a
import Data.List
splitOn " " "a b c"
This gave also the error message
Variable not in scope: splitOn :: [Char] -> [Char] -> t
Install the split library to be able to use it. Since you're a stack user here are the commands for that:
stack build split # install split (some people prefer "stack build" over "stack install", but the difference concerns only executables)
stack ghci # start ghci using the environment of packages installed by stack
I am saving some commands in a Haskell script in a .hs file while working thru a Haskell textbook. Here's a small example.
fst (1,2)
snd (1,2)
When I run these commands from the prelude in GHCi, they work fine. When I try to compile the .hs file with these two lines, I get the following:
ch4_test.hs:2:1: error:
Parse error: module header, import declaration
or top-level declaration expected.
|
2 | fst (1,2)
| ^^^^^^^^^
Failed, no modules loaded.
I've googled this error and can't find any explanation what I'm doing wrong.
From a newbie to future newbies: The interactive environment ghci would lead you to believe that you can punch some expressions into an .hs file and run the thing (in a similar fashion to languages like swift and ruby). This is not the case.
Haskell needs an entrypoint called main. Quoting:
Here is a simple program to read and then print a character:
main :: IO ()
main = do c <- getChar
putChar c
The use of the name main is important: main is defined to be the entry point of a Haskell program (similar to the main function in C), and must have an IO type, usually IO ()
Source: https://www.haskell.org/tutorial/io.html
You can't just put any expression in a hs file.
As the error message says, you need a declaration here. For example:
main =
print (fst (1,2)) >>
print (snd (1,2))
I am getting this error but the cause appears to be completely different from anything posted here. And the error message is not at all helpful.
Using Cabal version 3.6.2.0 with GHCI 8.10.7 on MacOS High Sierra (10.13)
I'm working from this page: https://www.tutorialspoint.com/haskell/haskell_modules.htm
specifically the "custom modules" section. There you can see the code I copied and pasted.
Besides the tutorial not mentioning I needed to add "other-modules: Custom" to myfirstapp.cabal, and besides the fact that the sample Custom.hs file includes "if x 'rem' 2 == 0" rather than "if x rem 2 == 0", here is the problem:
Indentation matters!
This line (inside the quotes) does NOT work "if x rem 2 == 0".
This line DOES work " if x rem 2 == 0"!
Indenting by one space is the difference between success and failure.
I'm totally new to Haskell. I've programmed extensively in PHP, Javascript, and Applescript, and dabbled in a dozen others, and this is the first time I've seen white space matter. I assume this is commonly known amongst Haskell veterans, but it would certainly be nice if that was included prominently in the documentation.
I have many files that must be processed automatically. Each file holds the response of one student to an exercise which asks the student to give definitions for some functions given a type for each function.
My idea is to have an Haskell script that loads each student file, and verifies if each function has the expected type.
A constraint is that the student files are not defined as modules.
How can I do this?
My best alternative so far is to spawn a GHCi process that will read stdin from a "test file" with GHCi commands, for example:
:load student1.hs
:t g
... and so on ...
then parse the returned output from GHCi to find the types of the functions in the student file.
Is there another clean way to load an arbitrary Haskell file and introspect its code?
Thanks
Haskell does not save type information at runtime. In Haskell, types are used for pre-runtime type checking at the static analysis phase and are later erased. You can read more about Haskell's type system here.
Is there a reason you want to know the type of a function at runtime? maybe we can help with the problem itself :)
Edit based on your 2nd edit:
I don't have a good solution for you, but here is one idea that might work:
Run a script that for each student module will:
Take the name of the module and produce a file Test.hs:
module Test where
import [module-name]
test :: a -> b -> [(b,a)]
test = g
run ghc -fno-code Test.hs
check the output does not contain type errors
write results into a log file
I think if you have a dynamically determined number of .hs files, which you need to load, parse and introspect, you could/should use the GHC API instead.
See for example:
Using GHC API to compile Haskell sources to CORE and CORE to binary
https://mail.haskell.org/pipermail/haskell-cafe/2009-April/060705.html
These might not be something you can use directly — and I haven't done anything like this myself so far either — but these should get you started.
See also:
https://wiki.haskell.org/GHC/As_a_library
https://hackage.haskell.org/package/hint
The closest Haskell feature to that is Data.Typeable.typeOf. Here's a GHCi session:
> import Data.Typeable
> typeOf (undefined :: Int -> Char)
Int -> Char
> typeOf (undefined :: Int -> [Char])
Int -> [Char]
> typeOf (undefined :: Int -> Maybe [Char])
Int -> Maybe [Char]
> :t typeOf
typeOf :: Typeable a => a -> TypeRep
Under the hood, the Typeable a constraint forces Haskell to retain some type tags until runtime, so that they can be retrieved by typeOf. Normally, no such tags exist at runtime. The TypeRep type above is the type for such tags.
That being said, having such information is almost never needed in Haskell. If you are using typeOf to implement something, you are likely doing it wrong.
If you are using that to defer type checks to run time, when they could have been performed at compile time, e.g. using a Dynamic-like type for everything, then you are definitely doing it wrong.
If the function is supposed to be exported with a specific name, I think probably the easiest way would be to just write a test script that calls the functions and checks they return the right results. If the test script doesn't compile, the student's submission is incorrect.
The alternative is to use either the GHC API (kinda hard), or play with Template Haskell (simpler, but still not that simple).
Yet another possibility is to load the student's code into GHCi and use the :browse command to dump out everything that's exported. You can then grep for the term you're interested in. That should be quite easy to automate.
There's a catch, however: foo :: x -> x and foo :: a -> a are the same type, even though textually they don't match at all. You might contemplate trying to normalise the variable names, but it's worse: foo :: Int -> Int and foo :: Num x => x -> x don't look remotely the same, yet one type is an instance of the other.
...which I guess means I'm saying that my answer is bad? :-(
I've recently come across a bot on Twitter named EmojiHaskell, that claims to tweet 'interpretable Haskell code with emoji variable names'. A particular Tweet caught my attention, as it looked like malformed syntax to me, so I decided to take a closer look. So far I've produced the following code:
module Main where
🙏 :: [🍳] -> Maybe 🍳
🙏 [] = Nothing
🙏 (👽:as) = Just 👽
main = print $ 🙏 "♥"
Since I've used λ on occasion in my Haskell code, I expected this code to work, but it appears that GHC doesn't like the emoji at all.
With $ runhaskell Main.hs I get:
Main.hs:4:1: parse error on input ‘🙏’
I've already had a look at the UnicodeSyntax extension,
and tried to only use some or single emoji instead of all of them to see if a certain one provokes the problem.
Now my question is this:
Is there currently a Haskell compiler that would accept the code?
Can I get GHC to work with this code somehow?
That code is not valid haskell. The reason is that 🙏 (like, probably, all Emojis) is a symbol character:
Prelude> import Data.Char
Prelude Data.Char> generalCategory '🙏'
OtherSymbol
But you can still use them like any other symbol, namely as an operator:
Prelude Data.Char> let (🙏) = (+)
Prelude Data.Char> 32 🙏 42
74
Furthermore, as user3237465 pointed out, if you use the prefix syntax for operators, i.e. put it in parentheses, you can even use it like any other symbol:
(🙏) :: [a] -> Maybe a
(🙏) [] = Nothing
(🙏) ((👽):as) = Just (👽)
main = print $ (🙏) "♥"
This is almost the example in the original post. Unfortunately, this trick does not work for the type variable. The the documentation is worded a bit unfortunately, but in fact symbols are never type variables and always type constructors
If I have a Name in TemplateHaskell and want to find out the value of the variable that it names, provided that the variable is declared as a literal, can this be done?
var = "foo"
-- Can `contentsOf` be defined?
$((contentsOf . mkName $ "var") >>= guard . (== "foo"))
In theory, yes. In practice, no.
Finding out stuff about existing names is done using reify :: Name -> Q Info, and for a definition like that you would get back a VarI value, which includes a Maybe Dec field. This would seem to suggest that you might in some cases be able to get the syntax tree for the declaration of the variable, which would allow you to extract the literal, however current versions of GHC always returns Nothing in this field, so you're out of luck for a pure TH solution.
However, TH does allow arbitrary IO actions to be run, so you could potentially work around this by loading and parsing the module yourself using something like haskell-src-exts, however I suspect that would be more trouble than it's worth.