Instance read Haskell - haskell

I need to implement a read instance of the data type
data GameAction = GameAction (Int, Int) deriving (Eq)
I did this
instance Read GameAction where
readProc (x:xs:_) = setGA (read x) (read xs)
But i get the error
`readProc' is not a (visible) method of class `Read'
any idea??

Firstly, try to include more information and context in your question next time as it's helpful.
Second, it appears as if your issue is simply a typo: readProc vs. the actual readPrec method in the Read typeclass.
Third, implementing Read is not neccesary here as it can be easily derived:
data GameAction = GameAction (Int, Int) deriving (Show,Eq,Read)
And in ghci:
ghci> let x = GameAction (5,6)
ghci> (read . show) x == id x
True
So there you go.
But more importantly, why are you trying to implement a Read instance by hand? Show and Read are for encoding/decoding data types to and from String, which should only be used for debug purposes. If you want something more specialized than what the automatically derived Read instance gives you, you're probably looking for something more than what Read should be used for. If you want to parse UTF-8 strings into data types, look at combining the text library with the attoparsec library.

Thanks you all.
I could solve my problem like follow
instance Read GameAction where
readsPrec _ (x:y:rest) = let board = read [x] :: Int;
cel = read [y] :: Int;
in
if all isDigit [x,y] then
[(setGA board cel, rest)]
else []
readsPrec _ _ = []

Related

instance declaration and convert string to Maybe type

An guessing and answering game.
Each Card comprises a Suit, one of A,B,C,D,E,F,G, and a Rank, one of 1|2|3.
I need to have a function to guarantee input(String) whether is valid type. And also write an instance declaration so that the type is in the Show class.
I am not sure about the function toCard, how to express "String" in the function and meet it with the condition.
data Suit = A|B|C|D|E|F|G
deriving (Show , Eq)
data Rank = R1|R2|R3
deriving (Show, Eq)
data Card = Card Suit Rank
deriving (Show, Eq)
instance Show Card where show (Card a b)
= show a ++ show (tail show b)
toCard :: String -> Maybe Card
toCard all#(x:xs)
| (x=A|B|C|D|E|F)&&(xs==1|2|3) = Just Card
| otherwise = Nothing
edit toCard function, input should be any String, so i use a list expression, but it seems to be not correct, cause i try it in ghci, (x=A|B|C|D|E|F)&&(y==1|2|3) is not valid
1) Firstly,
instance Show Card where show (Card a b)
= show a ++ show (tail show b)
You have automatically derived a Show instance for Card, so this will conflict (you can only have 1 instance), and further it won't compile. The show should go on a new line, and tail should be applied to the result of show b.
instance Show Card where
show (Card a b) = show a ++ " " + tail (show b)
2) Secondly,
toCard :: String -> Maybe Card
toCard all#(x:xs)
| (x=A|B|C|D|E|F)&&(xs==1|2|3) = Just Card
| otherwise = Nothing
The syntax (x=A|B|C|D|E|F)&&(xs==1|2|3) is pretty wild, and certainly not valid Haskell. The closest approximation would be something like, x `elem` ['A','B','C','D','E','F'] && xs `elem` ["1","2","3"], but as you can see this rapidly becomes boilerplate-y. Also, Just Card makes no sense - you still need to use the x and xs to say what the card actually is! eg. Just $ Card x xs (though that still won't work because they're still character/string not Suit/Rank).
One solution would be to automatically derive a Read instance on Rank, Suit, and Card. However, the automatic derivation for read on Card would require you to input eg. "Card A R1", so let's try using the instance on Rank and Suit to let us write a parser for Cards that doesn't require prefixed "Card".
First attempt:
toCard :: String -> Maybe Card
toCard (x:xs) = Just $ Card (read [x] :: Suit) (read xs :: Rank)
Hmm, this doesn't really allow us to deal with bad inputs - problem being that read just throws errors instead of giving us a Maybe. Notice however that we use [x] rather than x because read applies to [Char] and x :: Char. Next attempt:
import Text.Read (readMaybe)
toCard :: String -> Maybe Card
toCard [] = Nothing
toCard (x:xs) = let mSuit = readMaybe [x] :: Suit
mRank = readMaybe xs :: Rank
in case (mSuit, mRank) of
(Just s, Just r) -> Just $ Card s r
_ -> Nothing
This copes better with bad inputs, but has started to get quite long. Here's two possible ways to shorten it again:
-- using the Maybe monad
toCard (x:xs) = do mSuit <- readMaybe [x]
mRank <- readMaybe xs
return $ Card mSuit mRank
-- using Applicative
toCard (x:xs) = Card <$> readMaybe [x] <*> readMaybe xs
A parser library, though it comes with a steeper learning curve, makes this simpler. For this example, we'll use Text.Parsec, from the parsec library. Import it, and define a type alias for using in defining your parsers.
import Text.Parsec
type Parser = Parsec String () -- boilerplate
Parsec String () indicates a type of parser that consumes a stream of characters, and can produce a value of type () after parsing is complete. (In this case, we only care about the parsing, not any computation done along side the parsing.)
For your core types, we'll define a Show instant by hand for Rank so that you don't need to strip the R off later. We'll also derive a Read instance for Suit to make it easier to convert a string like "A" to a Suit value like A.
data Suit = A|B|C|D|E|F|G deriving (Show, Read, Eq)
data Rank = R1|R2|R3 deriving (Eq)
-- Define Show yourself so you don't constantly have to remove the `R`
instance Show Rank where
show R1 = "1"
show R2 = "2"
show R3 = "3"
data Card = Card Suit Rank deriving Eq
instance Show Card where
show (Card s r) = show s ++ show r
With that out of the way, we can define some parsers for each type.
-- Because oneOf will fail if you don't get one
-- of the valid suit characters, read [s] is guaranteed
-- to succeed. Using read eliminates the need for a
-- large case statement like in rank, below.
suit :: Parser Suit
suit = do
s <- oneOf "ABCDEF"
return $ read [s]
rank :: Parser Rank
rank = do
n <- oneOf "123"
return $ case n of
'1' -> R1
'2' -> R2
'3' -> R3
-- A Card parser just combines the Suit and Rank parsers
card :: Parser Card
card = Card <$> suit <*> rank
-- parse returns an Either ParseError Card value;
-- you can ignore the exact error if the parser fails
-- to return Nothing instead.
toCard :: String -> Maybe Card
toCard s = case parse card "" s of
Left _ -> Nothing
Right c -> Just c
oneOf is a predefined parser that consumes exactly one of the items in the given list.
parse takes three arguments:
A parser
A "source name" (only used for error message; you can use any string you like)
The string to parse

How to convert string to an actual term in Haskell?

I have defined the following data type
data EventType = RUN_EVENT Integer | GIVE_ITEM Integer Integer ... deriving (Show)
and from some test, I'm retrieving data as below
["EVENT","6001","E","RUN_EVENT","6010"]
and when I process the data, if, for example, after "E", I get "RUN_EVENT", I would like to construct a data of type EventType having the value RUN_EVENT 6010.
To do that, I can create a huge list that basically says that if I face with "RUN_EVENT" then construct a value with value RUN_EVENT, but this would not be efficient, so is there any way to convert "RUN_EVENT" to a term RUN_EVENT so that I can use it as
exec = (stringToTerm "RUN_EVENT") 6010
Here is a debatably hacky solution using Read
import Text.Read (readMaybe)
data EventType = RUN_EVENT Integer | GIVE_ITEM Integer Integer ...
deriving (Read, Show)
parseChunk :: [String] -> Maybe EventType
parseChunk = readMaybe . unwords
This will work like
parseChunk ["RUN_EVENT","4"] --> Just (RUN_EVENT 4)
parseChunk ["GIVE_ITEM","1","2"] --> Just (GIVE_ITEM 1 2)
parseChunk ["RUN_EVENT","4","5"] --> Nothing -- too many arguments
The reason it is hacky is that it relies on string manipulation to convert your data stream into a Haskell expression (which read parses). If your parser grows in complexity, the approach may break down, or the hackiness of it might get out of hand. Imagine that one of your constructors takes a list, then you have to start inserting "[" and "," into the stream before you read it.
If you want more control, the better way is to write a proper parser, maybe using Parsec or its ilk. But you will either have to list all the cases manually or generate the cases using generics. My own aesthetic would allow the read solution to stand for now, but then switch to a formal parser if it looked like it was getting at all messy.
Derive your data from Read type class. Then define the function as follows
data EventType = RUN_EVENT Integer | GIVE_ITEM Integer Integer ... deriving (Show, Read)
stringToTerm :: String -> Integer -> EventType
stringToTerm stringEvent n = read $ stringEvent ++ " " ++ show n
Keep in mind that the type annotation is important because of the read instance. The function stringToTerm can be partially applied to get what you want
Regards
Hacky solution, with -XViewPatterns for the added clarity
stringToTerm [] = []
stringToTerm ("EVENT":(read -> num):xs) = EVENT num : stringToTerm xs
stringToTerm ("RUN_EVENT":(read -> num1):(read -> num2):xs) = RUN_EVENT num1 num2 : stringToTerm xs
This allows you not to write a real parser, thus saving you the trouble, but will blow up if there's incorrect data
A direct implementation of your question might be:
parseEventType :: [String] -> EventType
parseEventType ["EVENT", _, _, "RUN_EVENT", i] = RUN_EVENT (read i)
parseEventType ["EVENT", i, _, "GIVE_ITEM", j] = GIVE_ITEM (read i) (read j)
parseEventType x = error ("parseEventType: could not parse " ++ show x)
The GIVE_ITEM case might not be correct but it should give you an idea.
However, this has some issues, mainly around error handling: What do you do if arguments are not integers or if the shape of the list doesn't match up with one of your types? It would be easiest to use Maybe:
parseEventType :: [String] -> Maybe EventType
parseEventType ["EVENT", _, _, "RUN_EVENT", i] = RUN_EVENT <$> readMay i
parseEventType ["EVENT", i, _, "GIVE_ITEM", j] = GIVE_ITEM <$> readMay i <*> readMay j
parseEventType x = Nothing
This shows off the applicative style.

Show matrix function in haskell

I've just started learning functional programming with Haskell and I need your help in the case below.
The idea is to display a Matrix using the show function in the following way:
> Mat [[1,2,3],[4,5,6]]
1 2 3
4 5 6
I already have a suggested solution that achieves the above outcome, but I do not particularly understand it.
data Mat a = Mat {mrows :: [[a]]}
instance (Show a) => Show (Mat a) where
show = unlines . map (unwords . map show) . mrows
I have searched on the internet regarding this part Mat {mrows :: [[a]]} but could not find any helpful answer. Why we can't just declare it as Mat [[a]]?
Also, how does exactly the last line achieves the above outcome. My apologies if the answer is too obvious, but I literally just started learning Haskell.
It is actually no problem - if you want to you can declare it this way
data Mat a = Mat [[a]]
then you just have to alter the show instance declaration a bit
instance (Show a) => Show (Mat a) where
show (Mat x) = unlines $ map (unwords . map show) x
Edit
The other approach has a few upsides:
If you want to get a bit more performance you can change the data keyword to newtype.
Moreover if you want to assert that this list of lists contain only lists of the same size - you can not export the constructor Mat but provide a 'smart' constructor mat :: [[a]] -> Maybe (Mat a) like:
mat x = if (length $ nub $ map length x) <= 1) then Just x else Nothing
but with the latter approach you can always still extract the [[a]] part if you export mrows
module Mat (Mat, mrows, mat) where ...
would hide the Mat construcor, but export the type of Mat where
module Mat (Mat(..), mat) ...
would export everything
Edit2
AAAAAnother thing - if you have a type with multiple records say
data Pirate = Pirate { head :: HeadThing
, rightArm :: ArmThing
, leftArm :: ArmThing
, rightLeg :: LegThing
, leftLeg :: LegThing}
data ArmThing = ...
data HeadThing = ...
data LegThing = ...
you can update one (or more "members") with record syntax - i.e.
redBeard :: Pirate
redBeard = blackbeard {head = RedBeard, rightArm = Hook}
data Mat a = Mat {mrows :: [[a]]}
This is Haskell's "record syntax". (That's the term you want to search for.) The above declaration is identical to
data Mat a = Mat [[a]]
The difference is that the second one declares a Mat constructor with an "unnamed" field of type [[a]], which the first one names the field mrows. In particular, this auto-defines a function
mrows :: Mat a -> [[a]]
that "unwraps" the Mat constructor. You can also use the name mrows in patterns, but that's generally more useful for constructors with dozens of fields, not just one.
A named field can always be referred to using unnamed syntax as well, so the named version does everything the unnamed version does plus a bit more.

How to do a Read instance for a simple custom format of data

I'm trying to use a short and easy to read format to show and read my data, and I would like that it could be used from the Haskell interpreter, in order to write hand or copy-paste inputs while I try new functions.
My data is a list of Int numbers, each one with an boolean property, that I associate with + and -, being the first one the default, so it doesn't need explicit representation (as with usual sign). I would like to represent the - after the number, like in this example:
[2, 5-, 4, 0-, 1, 6-, 2-]
Note that I can not use the usual sign because I need to be able of assigning - to 0, so that 0- is different than 0 (also, may be in the future I will need to use negative numbers, like in [-4-, -2]).
I did the easy part, which is to define the data type for the terms of the list and implement the show function.
data Term = T Int Bool deriving (Eq)
instance Show Term where
show (T v True) = show v
show (T v False) = show v ++ "-"
What I don't know is how to do the corresponding read function, or whether I cannot use the - sign, because it is a sign of the Haskell language. Suggestions are welcome.
Try something like this:
instance Read Term where
readsPrec n s = do
(i,rest) <- readsPrec (n+1) s -- read `i :: Int`
return $ case rest of -- look at the rest of the string
('-':rest') -> (T i False, rest') -- if it starts with '-'...
rest' -> (T i True, rest') -- if it doesn't...
Read in Haskell follows closely the idea that a parser can be represented by the type String -> [(a, String)] (this type is given the type synonym ReadS. To familiarize yourself with this idea of parsing, I recommend the reading the following functional pearl on monadic parsing.
Then, from GHCi:
ghci> read "[2, 5-, 4, 0-, 1, 6-, 2-]" :: [Term]
[2,5-,4,0-,1,6-,2-]
I like very much the answer of Alec, which I accepted. But after reading, thinking and trying, I reached another quite simple solution, that I would like to share here.
It uses reads instead of readsPrec because the Term constructor is not infix, so we don't need to manage precedence, and it is not monadic.
instance Read Term where
readsPrec _ s =
[(T v False, rest) | (v, '-' : rest) <- reads s] ++
[(T v True , rest) | (v, rest) <- reads s]
The symmetry with the corresponding Show instance is notable:
instance Show Term where
show (T v True) = show v
show (T v False) = show v ++ "-"

Haskell data serialization of some data implementing a common type class

Let's start with the following
data A = A String deriving Show
data B = B String deriving Show
class X a where
spooge :: a -> Q
[ Some implementations of X for A and B ]
Now let's say we have custom implementations of show and read, named show' and read' respectively which utilize Show as a serialization mechanism. I want show' and read' to have types
show' :: X a => a -> String
read' :: X a => String -> a
So I can do things like
f :: String -> [Q]
f d = map (\x -> spooge $ read' x) d
Where data could have been
[show' (A "foo"), show' (B "bar")]
In summary, I wanna serialize stuff of various types which share a common typeclass so I can call their separate implementations on the deserialized stuff automatically.
Now, I realize you could write some template haskell which would generate a wrapper type, like
data XWrap = AWrap A | BWrap B deriving (Show)
and serialize the wrapped type which would guarantee that the type info would be stored with it, and that we'd be able to get ourselves back at least an XWrap... but is there a better way using haskell ninja-ery?
EDIT
Okay I need to be more application specific. This is an API. Users will define their As, and Bs and fs as they see fit. I don't ever want them hacking through the rest of the code updating their XWraps, or switches or anything. The most i'm willing to compromise is one list somewhere of all the A, B, etc. in some format. Why?
Here's the application. A is "Download a file from an FTP server." B is "convert from flac to mp3". A contains username, password, port, etc. information. B contains file path information. There could be MANY As and Bs. Hundreds. As many as people are willing to compile into the program. Two was just an example. A and B are Xs, and Xs shall be called "Tickets." Q is IO (). Spooge is runTicket. I want to read the tickets off into their relevant data types and then write generic code that will runTicket on the stuff read' from the stuff on disk. At some point I have to jam type information into the serialized data.
I'd first like to stress for all our happy listeners out there that XWrap is a very good way, and a lot of the time you can write one yourself faster than writing it using Template Haskell.
You say you can get back "at least an XWrap", as if that meant you couldn't recover the types A and B from XWrap or you couldn't use your typeclass on them. Not true! You can even define
separateAB :: [XWrap] -> ([A],[B])
If you didn't want them mixed together, you should serialise them seperately!
This is nicer than haskell ninja-ery; maybe you don't need to handle arbitrary instances, maybe just the ones you made.
Do you really need your original types back? If you feel like using existential types because you just want to spooge your deserialised data, why not either serialise the Q itself, or have some intermediate data type PoisedToSpooge that you serialise, which can deserialise to give you all the data you need for a really good spooging. Why not make it an instance of X too?
You could add a method to your X class that converts to PoisedToSpooge.
You could call it something fun like toPoisedToSpooge, which trips nicely off the tongue, don't you think? :)
Anyway this would remove your typesystem complexity at the same time as resolving the annoying ambiguous type in
f d = map (\x -> spooge $ read' x) d -- oops, the type of read' x depends on the String
You can replace read' with
stringToPoisedToSpoogeToDeserialise :: String -> PoisedToSpooge -- use to deserialise
and define
f d = map (\x -> spooge $ stringToPoisedToSpoogeToDeserialise x) -- no ambiguous type
which we could of course write more succincly as
f = map (spooge.stringToPoisedToSpoogeToDeserialise)
although I recognise the irony here in suggesting making your code more succinct. :)
If what you really want is a heterogeneous list then use existential types. If you want serialization then use Cereal + ByteString. If you want dynamic typing, which is what I think your actual goal is, then use Data.Dynamic. If none of this is what you want, or you want me to expand please press the pound key.
Based on your edit, I don't see any reason a list of thunks won't work. In what way does IO () fail to represent both the operations of "Download a file from an FTP server" and "convert from flac to MP3"?
I'll assume you want to do more things with deserialised Tickets
than run them, because if not you may as well ask the user to supply a bunch of String -> IO()
or similar, nothing clever needed at all.
If so, hooray! It's not often I feel it's appropriate to recommend advanced language features like this.
class Ticketable a where
show' :: a -> String
read' :: String -> Maybe a
runTicket :: a -> IO ()
-- other useful things to do with tickets
This all hinges on the type of read'. read' :: Ticket a => String -> a isn't very useful,
because the only thing it can do with invalid data is crash.
If we change the type to read' :: Ticket a => String -> Maybe a this can allow us to read from disk and
try all the possibilities or fail altogether.
(Alternatively you could use a parser: parse :: Ticket a => String -> Maybe (a,String).)
Let's use a GADT to give us ExistentialQuantification without the syntax and with nicer error messages:
{-# LANGUAGE GADTs #-}
data Ticket where
MkTicket :: Ticketable a => a -> Ticket
showT :: Ticket -> String
showT (MkTicket a) = show' a
runT :: Ticket -> IO()
runT (MkTicket a) = runTicket a
Notice how the MkTicket contstuctor supplies the context Ticketable a for free! GADTs are great.
It would be nice to make Ticket and instance of Ticketable, but that won't work, because there would be
an ambiguous type a hidden in it. Let's take functions that read Ticketable types and make them read
Tickets.
ticketize :: Ticketable a => (String -> Maybe a) -> (String -> Maybe Ticket)
ticketize = ((.).fmap) MkTicket -- a little pointfree fun
You could use some unusual sentinel string such as
"\n-+-+-+-+-+-Ticket-+-+-+-Border-+-+-+-+-+-+-+-\n" to separate your serialised data or better, use separate files
altogether. For this example, I'll just use "\n" as the separator.
readTickets :: [String -> Maybe Ticket] -> String -> [Maybe Ticket]
readTickets readers xs = map (foldr orelse (const Nothing) readers) (lines xs)
orelse :: (a -> Maybe b) -> (a -> Maybe b) -> (a -> Maybe b)
(f `orelse` g) x = case f x of
Nothing -> g x
just_y -> just_y
Now let's get rid of the Justs and ignore the Nothings:
runAll :: [String -> Maybe Ticket] -> String -> IO ()
runAll ps xs = mapM_ runT . catMaybes $ readTickets ps xs
Let's make a trivial ticket that just prints the contents of some directory
newtype Dir = Dir {unDir :: FilePath} deriving Show
readDir xs = let (front,back) = splitAt 4 xs in
if front == "dir:" then Just $ Dir back else Nothing
instance Ticketable Dir where
show' (Dir p) = "dir:"++show p
read' = readDir
runTicket (Dir p) = doesDirectoryExist p >>= flip when
(getDirectoryContents >=> mapM_ putStrLn $ p)
and an even more trivial ticket
data HelloWorld = HelloWorld deriving Show
readHW "HelloWorld" = Just HelloWorld
readHW _ = Nothing
instance Ticketable HelloWorld where
show' HelloWorld = "HelloWorld"
read' = readHW
runTicket HelloWorld = putStrLn "Hello World!"
and then put it all together:
myreaders = [ticketize readDir,ticketize readHW]
main = runAll myreaders $ unlines ["HelloWorld",".","HelloWorld","..",",HelloWorld"]
Just use Either. Your users don't even have to wrap it themselves. You have your deserializer wrap it in the Either for you. I don't know exactly what your serialization protocol is, but I assume that you have some way to detect which kind of request, and the following example assumes the first byte distinguishes the two requests:
deserializeRequest :: IO (Either A B)
deserializeRequest = do
byte <- get1stByte
case byte of
0 -> do
...
return $ Left $ A <A's fields>
1 -> do
...
return $ Right $ B <B's fields>
Then you don't even need to type-class spooge. Just make it a function of Either A B:
spooge :: Either A B -> Q

Resources