Yesod's shakespearean templates (hamlet) and IO - haskell

In Hamlet, how does one uses the result of an IO operation inside #{...} ?
For instance :
someIO :: IO String
-----------------
$with stuff <- someIO
<p>#{stuff}
Fails with
No instance for (blaze-markup-0.6.0.0:Text.Blaze.ToMarkup
(IO String))
arising from a use of `toHtml'
I fear that I have not approached the problem from the right angle, could someone shed some light on this issue for me?
Thank you

Hamlet is just providing an alternate syntax for normal Haskell code, so like normal Haskell, you have to keep your impure actions separate. In other words, you need to run the IO action outside of the template.

Related

How to introspect an Haskell file to get the types of its definitions

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? :-(

Disable printing of IO results in GHCi?

When running IO actions in GHCi prompt it automatically runs the action and shows result, this is nice, but not for students trying to understand difference between IO and non-IO. Is there a way to change configuration of GHCi so that it runs the action, but shows something like <<IO Int action>> instead? Something more like result for ST actions (but action should be performed):
now it does:
> return 1 :: IO Int
1
> return 1 :: ST s Int
<<ST action>>
i would like:
> return 1 :: IO Int
<<IO Int action>>
> putStrLn "bla"
bla
<<IO () action>>
Edit:
I just found that IO is probably the only thing handled specially by GHCi, ST actually has instance for Show (ST s a) which returns "<<ST action>>". So maybe if I could disable this special treatment of IO it would be sufficient.
As for allowed code changes: manually changing evaluated expression is not an option. Change in libraries might be, but I would prefer not to do that (I considered creating wrapped IO type, but then interpreter will not run the action). If GHCi could automatically wrap IO actions somehow, that would be an option.
This is an interesting question. The only thing I can come up with is writing some kind of custom prelude module that exports a type called IO, but which isn't "the" I/O type that GHCi is special-casing.
Of course, this is no help at all unless the student remembers to import this rather than the real prelude. I suppose you could write that into the GHCi config file, but... well, it's certainly not perfect.
The only other way I can think of is to use the GHC-API to basically reimplement GHCi yourself. But that sounds like waaaay too much work...

Compiling / testing Haskell without a main function

I'm working on an assignment in Haskell. However, the base code I am working with does not have a main function defined, and from the wording of the assignment I believe I am not expected to have to write any code outside of the solution to the problem. However, when I try to compile my code, I receive the error:
The IO function 'main' is not defined in module 'Main'
I assume this is because the function does not have a main function. However, when I try to write my own main function:
main :: IO ()
main = solve easy // easy is an array
I get the error:
Couldn't match expected type 'IO()' with actual type '[Int]'
The solve function's type is declared as follows:
solve :: [Int] -> [Int]
So it takes an array and returns an array. What am I doing wrong in writing my main function? Even when I try changing the declaration of main to things like:
main :: [Int]
or
main :: IO [Int]
I still can't get it to compile.
Without writing a proper main with a correct type, as described by #G Philip, you can load your file in ghci by writing ghci file.hs in your terminal, or by invoking :l file.hs inside ghci.
Firstly: the function main must have type IO t for some type t. When the program is executed, the computation defined by main is executed, and its result (of type t) is thrown away; see here.
So, in particular, you cannot have the type of main as [Int] and have the compiler not complain.
Depending on whether you want to see the results of solving the easy case or not, you can try one of the following:
If you want to see the results: print them!
main :: IO ()
main = putStrLn $ show (solve easy)
If you are not interested in seeing the results, throw them away:
main :: IO ()
main = let solution = solve easy
in putStrLn ""
Edit: Note, however, that if you do the latter, then (as #yatima2975 mentions in a comment) the "solve easy" part will not be evaluated.
Just to add to the other answers:
you don't need to write a main function and can still compile the file into a lib and the easiest way to do this is just giving a module name (that is not Main):
module MyCode where
solve :: ...
But of course compiling it might not make any sense anymore (as you will not be able to run it - and of course even if you have not specified what to output anyway).
So in this case rather load the file into ghci:
ghci MyFile.hs
and then everytime you changed something in your code you can do :r inside ghci to reload it.
Or even better set up your favorite editor (emacs and vi are quite easy but sublime text and some other works great too) to give you integrated ghci - this explains what you need to do to setup emacs with haskell-mode if you are interested.
Consider
main :: IO ()
main = do
let res = solve easy // easy is an array
return ()
where return () yields a result of type Unit which conveys with the type signature of main. Note solve easy is bound to res which is not used further.

Safely serialize Text to Bytestring

The text package does not provide an instance of Binary to encode/decode text. I have read about and understand the reasoning behind this (namely, Text should be encoding-agnostic). However, I need a Binary instance of Text. I've found that there is a package called text-binary that does this. However, the instance is as follows:
instance Binary T.Text where
put = put . T.encodeUtf8
get = T.decodeUtf8 <$> get
Pretty good, except that decodeUtf8 is a partial function, so I'd rather be using decodeUtf8' and passing the failure through the Get monad. I can't figure out how to fail correctly with the Get monad. Just from looking around in Data.Binary.Get, I see this:
data Decoder a = Fail !B.ByteString {-# UNPACK #-} !ByteOffset String
| Partial (Maybe B.ByteString -> Decoder a)
| Done !B.ByteString {-# UNPACK #-} !ByteOffset a
Which seems to indicate that there is a way to do what I want. I just can't see how the library authors intend for it to be used. I appreciate any insights that a more learned mind than my own has to offer.
Well, though we tend to disregard it, the Monad class still has that yucky fail method:
get = do
utf8'd <- get
case T.decodeUtf8' utf8'd of
Just t -> return t
Nothing -> fail "No parse for UTF-8 Text"
I'm not sure if it should still be considered "correct" to use fail, but it seems to be the obvious thing for a case like this. I suppose even if it's removed from the Monad class, there'll be some other class MonadPlus m => MonadFail m where fail :: String -> m a which Get will be an instance of.

Is there no standard (Either a) monad instance?

I was under the impression that there was an instance for Either a somewhere, but I can't seem to find it. I have tried importing Control.Monad, Control.Monad.Instances and Data.Either as shown
module Main where
import Control.Monad
import Data.Either
import Control.Monad.Instances
test :: [Either a b] -> Either a [b]
test = sequence
main = return ()
but ghc tells me that it could not deduce (Monad (Either a)). Adding
instance Monad (Either a) where
return = Right
Right b >>= f = f b
Left a >>= _ = Left a
makes the code compile, but this instance declaration seems so general that it doesn't make sense to me if it isn't already out there in some standard module. If it is, where should I look to find it, and if it isn't, is there then a reason for this?
-------------- EDIT ---------------
Be aware that I now think that the answer by user31708 below ("As of base 4.6, the instance is in Data.Either itself.") is currently the correct answer. I am not sure of the proper protocol of reassigning the selected answer in this case, where the selected answer was the correct answer at the time that the question was asked, so I have left it as it is. Please correct me, if there is another guideline for this.
This instance has been added in base 4.3.x.x, which comes with ghc 7. Meanwhile, you can use the Either instance directly, or, if you are using Either to represent something
that may fail you should use ErrorT monad transformer.
As of base 4.6, the instance is in Data.Either itself.
There is not an instance for Either a, but there is for Either String in Control.Monad.Error. (Actually, it's for Error e => Either e, IIRC).
I believe there's something in Control.Monad.Error - don't have anything to check, though.

Resources