Safely serialize Text to Bytestring - haskell

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.

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

Adapting Error to Except

Now that Control.Monad.Error is deprecated, and Control.Monad.Except reigns supreme, a lot of sources online haven't caught up, and still show examples of how to use Error.
So how would I go about turning
instance Error MyError where
noMsg = ...
strMsg = ...
into something using Except. Just replacing Error with Except didn't work as Except expects additional type parameters
I understand that those exact methods don't exist in Except, so what's the alternative?
Short answer is: Replace Error by nothing at all, replace ErrorT by ExceptT, and things should continue to work as long as you don't use Errors methods, fail (which now has a different definition), or failing pattern matches in do notation.
The essential difference between the old Control.Monad.Error system and the new Control.Monad.Except system is that the new system imposes no class restriction on the error/exception type.
It was found that the ability to use any error/exception type at all, polymorphically, was more useful than the somewhat hacky ability to customize conversion of string error messages.
So the class Error has simply disappeared.
As a side effect, fail for ExceptT now is lifted from the underlying monad. This also changes the effect of failing patterns in do notation.
The old definition was:
fail msg = ErrorT $ return (Left (strMsg msg))
which I think is equivalent to
fail msg = throwError (strMsg msg)
If you still need this behavior, you can instead use
throwError yourIntendedErrorValue
(throwE works instead if you're using transformers (i.e. Control.Monad.Trans.Except) rather than mtl.)
The old do pattern matching failure would apply to things like
do
Just x <- myErrorTAction
...
when the action actually returns Nothing. This is more awkward, but you could e.g. replace it with an explicit case match (essentially desugaring it):
do
y <- myErrorTAction
case y of
Nothing -> throwE ...
Just x -> do
...
#DanielWagner suggests the following to avoid extra indentation:
do
x <- myErrorTAction >>= maybe (throwError ...) return
...
The removal of Error also eliminates the need for an inconsistency in naming that Control.Monad.Error had: Most transformers follow the rule that SomethingT is the name of the transformer, and Something is a type alias for SomethingT ... Identity. The old ErrorT broke that because the Error class was used for something entirely different.
In the new system, Except e = ExceptT e Identity, like for other transformers.

Alpha conversion on a Haskell expression

Given a Haskell expression, I'd like to perform alpha conversion, ie. rename some of the non free variables.
I've started implementing my own function for this, which works on a haskell-src-exts Exp tree, however it turns out to be surprisingly nontrivial, so I can't help wondering - is there an established easy-to-use library solution for this kind of source conversion? Ideally, it should integrate with haskell-src-exts.
This is one of the problems where the "Scrap Your Boilerplate" style generic libraries shine!
The one I'm most familiar with is the uniplate package, but I don't actually have it installed at the moment, so I'll use the (very similar) functionality found in the lens package. The idea here is that it uses Data.Data.Data (which is the best qualified name ever) and related classes to perform generic operations in a polymorphic way.
Here's the simplest possible example:
alphaConvert :: Module -> Module
alphaConvert = template %~ changeName
changeName :: Name -> Name
changeName (Ident n) = Ident $ n ++ "_conv"
changeName n = n
The (%~) operator is from lens and just means to to apply the function changeName to everything selected by the generic traversal template. So what this does is find every alphanumeric identifier and append _conv to it. Running this program on its own source produces this:
module AlphaConv where
import Language.Haskell.Exts
import Control.Lens
import Control.Lens.Plated
import Data.Data.Lens
instance Plated_conv Module_conv
main_conv
= do ParseOk_conv md_conv <- parseFile_conv "AlphaConv.hs"
putStrLn_conv $ prettyPrint_conv md_conv
let md'_conv = alphaConvert_conv md_conv
putStrLn_conv $ prettyPrint_conv md'_conv
alphaConvert_conv :: Module_conv -> Module_conv
alphaConvert_conv = template_conv %~ changeName_conv
changeName_conv :: Name_conv -> Name_conv
changeName_conv (Ident_conv n_conv)
= Ident_conv $ n_conv ++ "_conv"
changeName_conv n_conv = n_conv
Not terribly useful since it doesn't distinguish between identifiers bound locally and those defined in an outside scope (such as being imported), but it demonstrates the basic idea.
lens may seem a bit intimidating (it has a lot more functionality than just this); you may find uniplate or another library more approachable.
The way you'd approach your actual problem would be a multi-part transformation that first selects the subexpressions you want to alpha-convert inside of, then uses a transformation on those to modify the names you want changed.

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.

Simple Haskell Instance Question

I'm trying different data structures for implementing Prim's algorithm. So I made a class to abstract what I want to do:
class VertexContainer a where
contains :: a -> Vertex -> Bool
insert :: a -> WeightedEdge -> a
numVertices :: a -> Int
Now I want to use a heap (from Data.Heap) as my vertex container. But I can't for the life of me figure out the syntax. As you can see from the insert declaration, the container can only hold WeightedEdges, which are a data type. So I tried:
instance VertexContainer (Heap MinPolicy WeightedEdge) where
contains _ _ = True
It tells me it's an illegal type synonym. I've tried various other permutations, and none of them seem to work. Can anyone help me?
If you read the entire error message you'll find that it tells you how to be able to use a type synonym in an instance declaration, namely by using the language extension TypeSynonymInstances. E.g., you can pass -XTypeSynonymInstances on the command line.
I got it working by wrapping this into a newtype. Considered ugly. I guess you have to wait for one of the Haskell gurus to answer this.

Resources